files
  [1] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_004-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_005-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_006-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_011-dosage_plot.tsv" 
  [5] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_012-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_015-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_016-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_025-dosage_plot.tsv" 
  [9] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_026-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_027-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_028-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_029-dosage_plot.tsv" 
 [13] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_030-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_034-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_037-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_041-dosage_plot.tsv" 
 [17] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_042-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_043-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_044-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_045-dosage_plot.tsv" 
 [21] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_046-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_048-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_058-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_060-dosage_plot.tsv" 
 [25] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_062-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_064-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_065-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_072-dosage_plot.tsv" 
 [29] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_074-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_076-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_077-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_079-dosage_plot.tsv" 
 [33] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_081-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_086-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_088-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_090-dosage_plot.tsv" 
 [37] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_097-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_108-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_1157-dosage_plot.tsv" "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_116-dosage_plot.tsv" 
 [41] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_1160-dosage_plot.tsv" "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_117-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_1180-dosage_plot.tsv" "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_119-dosage_plot.tsv" 
 [45] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_1190-dosage_plot.tsv" "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_1192-dosage_plot.tsv" "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_1196-dosage_plot.tsv" "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_122-dosage_plot.tsv" 
 [49] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_123-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_124-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_126-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_128-dosage_plot.tsv" 
 [53] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_131-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_171-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_172-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_198-dosage_plot.tsv" 
 [57] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_204-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_205-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_219-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_220-dosage_plot.tsv" 
 [61] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_222-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_224-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_227-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_234-dosage_plot.tsv" 
 [65] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_236-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_238-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_244-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_247-dosage_plot.tsv" 
 [69] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_248-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_251-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_254-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_255-dosage_plot.tsv" 
 [73] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_256-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_257-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_258-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_259-dosage_plot.tsv" 
 [77] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_262-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_267-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_268-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_269-dosage_plot.tsv" 
 [81] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_270-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_272-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_273-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_274-dosage_plot.tsv" 
 [85] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_278-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_279-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_280-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_281-dosage_plot.tsv" 
 [89] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_286-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_289-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_292-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_293-dosage_plot.tsv" 
 [93] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_295-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_299-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_304-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_305-dosage_plot.tsv" 
 [97] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_306-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_308-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_309-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_311-dosage_plot.tsv" 
[101] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_313-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_349-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_361-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_363-dosage_plot.tsv" 
[105] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_365-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_372-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_373-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_387-dosage_plot.tsv" 
[109] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_396-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_397-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_398-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_401-dosage_plot.tsv" 
[113] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_403-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_406-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_407-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_414-dosage_plot.tsv" 
[117] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_415-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_417-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_420-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_421-dosage_plot.tsv" 
[121] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_425-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_428-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_429-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_430-dosage_plot.tsv" 
[125] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_433-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_435-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_439-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_449-dosage_plot.tsv" 
[129] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_450-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_452-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_454-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_456-dosage_plot.tsv" 
[133] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_459-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_460-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_461-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_463-dosage_plot.tsv" 
[137] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_464-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_465-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_466-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_467-dosage_plot.tsv" 
[141] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_469-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_473-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_474-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_477-dosage_plot.tsv" 
[145] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_479-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_480-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_483-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_485-dosage_plot.tsv" 
[149] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_487-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_488-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_493-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_494-dosage_plot.tsv" 
[153] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_497-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_499-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_500-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_502-dosage_plot.tsv" 
[157] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_505-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_509-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_510-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_513-dosage_plot.tsv" 
[161] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_514-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_522-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_523-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_525-dosage_plot.tsv" 
[165] "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_529-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_532-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_535-dosage_plot.tsv"  "../experiments/2_low_cov_cnv/data/plots/2x_LOP868_538-dosage_plot.tsv" 
[169] "../experiments/2_low_cov_cnv/data/plots/4x_LOP868-dosage_plot.tsv"     
names(all_dosage) 
  [1] "2x_LOP868_004"  "2x_LOP868_005"  "2x_LOP868_006"  "2x_LOP868_011"  "2x_LOP868_012"  "2x_LOP868_015"  "2x_LOP868_016"  "2x_LOP868_025"  "2x_LOP868_026"  "2x_LOP868_027"  "2x_LOP868_028"  "2x_LOP868_029"  "2x_LOP868_030"  "2x_LOP868_034"  "2x_LOP868_037"  "2x_LOP868_041" 
 [17] "2x_LOP868_042"  "2x_LOP868_043"  "2x_LOP868_044"  "2x_LOP868_045"  "2x_LOP868_046"  "2x_LOP868_048"  "2x_LOP868_058"  "2x_LOP868_060"  "2x_LOP868_062"  "2x_LOP868_064"  "2x_LOP868_065"  "2x_LOP868_072"  "2x_LOP868_074"  "2x_LOP868_076"  "2x_LOP868_077"  "2x_LOP868_079" 
 [33] "2x_LOP868_081"  "2x_LOP868_086"  "2x_LOP868_088"  "2x_LOP868_090"  "2x_LOP868_097"  "2x_LOP868_108"  "2x_LOP868_1157" "2x_LOP868_116"  "2x_LOP868_1160" "2x_LOP868_117"  "2x_LOP868_1180" "2x_LOP868_119"  "2x_LOP868_1190" "2x_LOP868_1192" "2x_LOP868_1196" "2x_LOP868_122" 
 [49] "2x_LOP868_123"  "2x_LOP868_124"  "2x_LOP868_126"  "2x_LOP868_128"  "2x_LOP868_131"  "2x_LOP868_171"  "2x_LOP868_172"  "2x_LOP868_198"  "2x_LOP868_204"  "2x_LOP868_205"  "2x_LOP868_219"  "2x_LOP868_220"  "2x_LOP868_222"  "2x_LOP868_224"  "2x_LOP868_227"  "2x_LOP868_234" 
 [65] "2x_LOP868_236"  "2x_LOP868_238"  "2x_LOP868_244"  "2x_LOP868_247"  "2x_LOP868_248"  "2x_LOP868_251"  "2x_LOP868_254"  "2x_LOP868_255"  "2x_LOP868_256"  "2x_LOP868_257"  "2x_LOP868_258"  "2x_LOP868_259"  "2x_LOP868_262"  "2x_LOP868_267"  "2x_LOP868_268"  "2x_LOP868_269" 
 [81] "2x_LOP868_270"  "2x_LOP868_272"  "2x_LOP868_273"  "2x_LOP868_274"  "2x_LOP868_278"  "2x_LOP868_279"  "2x_LOP868_280"  "2x_LOP868_281"  "2x_LOP868_286"  "2x_LOP868_289"  "2x_LOP868_292"  "2x_LOP868_293"  "2x_LOP868_295"  "2x_LOP868_299"  "2x_LOP868_304"  "2x_LOP868_305" 
 [97] "2x_LOP868_306"  "2x_LOP868_308"  "2x_LOP868_309"  "2x_LOP868_311"  "2x_LOP868_313"  "2x_LOP868_349"  "2x_LOP868_361"  "2x_LOP868_363"  "2x_LOP868_365"  "2x_LOP868_372"  "2x_LOP868_373"  "2x_LOP868_387"  "2x_LOP868_396"  "2x_LOP868_397"  "2x_LOP868_398"  "2x_LOP868_401" 
[113] "2x_LOP868_403"  "2x_LOP868_406"  "2x_LOP868_407"  "2x_LOP868_414"  "2x_LOP868_415"  "2x_LOP868_417"  "2x_LOP868_420"  "2x_LOP868_421"  "2x_LOP868_425"  "2x_LOP868_428"  "2x_LOP868_429"  "2x_LOP868_430"  "2x_LOP868_433"  "2x_LOP868_435"  "2x_LOP868_439"  "2x_LOP868_449" 
[129] "2x_LOP868_450"  "2x_LOP868_452"  "2x_LOP868_454"  "2x_LOP868_456"  "2x_LOP868_459"  "2x_LOP868_460"  "2x_LOP868_461"  "2x_LOP868_463"  "2x_LOP868_464"  "2x_LOP868_465"  "2x_LOP868_466"  "2x_LOP868_467"  "2x_LOP868_469"  "2x_LOP868_473"  "2x_LOP868_474"  "2x_LOP868_477" 
[145] "2x_LOP868_479"  "2x_LOP868_480"  "2x_LOP868_483"  "2x_LOP868_485"  "2x_LOP868_487"  "2x_LOP868_488"  "2x_LOP868_493"  "2x_LOP868_494"  "2x_LOP868_497"  "2x_LOP868_499"  "2x_LOP868_500"  "2x_LOP868_502"  "2x_LOP868_505"  "2x_LOP868_509"  "2x_LOP868_510"  "2x_LOP868_513" 
[161] "2x_LOP868_514"  "2x_LOP868_522"  "2x_LOP868_523"  "2x_LOP868_525"  "2x_LOP868_529"  "2x_LOP868_532"  "2x_LOP868_535"  "2x_LOP868_538"  "4x_LOP868"     
all_dosage <- files %>% 
  map(read_delim, delim = " ", col_names = T)
  
for (i in 1:length(files)) {
  all_dosage[[i]]$sample <- str_replace(files[i], "../experiments/2_low_cov_cnv/data/plots/", "")
  all_dosage[[i]]$sample <- gsub("-dosage_plot.tsv", "", all_dosage[[i]]$sample)
  all_dosage[[i]]$sample_num <- i
}

bin_dosage <- all_dosage %>% 
  bind_rows() %>% 
  mutate(sample = str_replace(sample, "-dosage_plot.tsv", "")) %>% 
  filter(sample != "2x_LOP868_279")

chrom_dosage <- bin_dosage %>% 
  group_by(chrom, sample, sample_num) %>% 
  summarize(chrom_readcount = sum(readcount)) %>% 
  arrange(sample, chrom) %>% 
  filter(!is.na(chrom)) %>% 
  ungroup()
with_totals <- chrom_dosage %>% 
  group_by(sample, sample_num) %>% 
  summarize(total_readcount = sum(chrom_readcount)) %>% 
  left_join(chrom_dosage, .) %>% 
  ungroup()
Joining, by = c("sample", "sample_num")
with_control <- with_totals %>% 
  filter(sample == "4x_LOP868") %>% 
  mutate(chromshort = str_replace(chrom, "chr", "")) %>% 
  mutate(chromshort = str_replace(chromshort, "^0", "")) %>% 
  rename(control_chrom_readcount = chrom_readcount) %>% 
  rename(control_total_readcount = total_readcount) %>%
  select(-sample, -sample_num) %>% 
  left_join(with_totals, .) %>% 
  mutate(normcov = 2* (chrom_readcount / total_readcount) / (control_chrom_readcount / control_total_readcount)) %>% 
  filter(!sample %in% c("4x_LOP868", "2x_LOP868_279"))
Joining, by = "chrom"
fig2A <- with_control %>% 
  filter(normcov <= mean(with_control$normcov + 3*sd(with_control$normcov))) %>% 
  ggplot(., aes(x = sample_num, y = normcov)) +
  geom_vline(xintercept = c(with_control$sample_num[which(with_control$normcov >= mean(with_control$normcov) + 3 * sd(with_control$normcov))]), color = "gray70") +
  geom_point() +
  geom_text(data = filter(with_control, normcov >= mean(with_control$normcov) + 3*sd(with_control$normcov)), aes(x = sample_num, y = normcov, label = chromshort), size = 5, fontface = "bold") +
  geom_line(y = mean(with_control$normcov), color = "green") +
  geom_line(y = mean(with_control$normcov) + 3 * sd(with_control$normcov), color = "red") +
  scale_x_continuous(breaks = c(1,167), labels = c("1", "167")) +
  scale_y_continuous(limits = c(1.6, 3.3)) +
  ggtitle("A") +
  labs(x = "Individual", y = "Chromosome\nCopy Number") +
  theme_bw() +
  theme(panel.grid = element_blank(),
        panel.background=element_rect(fill="white",color="black"),
        axis.title.x=element_text(size=18),
        axis.title.y=element_text(size=18,angle= 90, vjust=0.5), plot.title=element_text(size=24,face="bold",hjust=0,color="black"),
        axis.text.x=element_text(size=18,color="black"),
        axis.text.y=element_text(size=18,color="black"),
        panel.grid.major.x = element_line(color = "gray70"))
fig2A

# ggsave("Fig2A.pdf", plot=fig2A, width = 18, height = 3, units = "in", device = "pdf")

This is a mathematical representation of trisomy, so I can use this to go back and make overlay plots wihthout having to manually specify them.

trisomics <- with_control$sample[which(with_control$normcov >= mean(with_control$normcov) + 3 * sd(with_control$normcov))]
chrom_overlay <- function(df, chr) {
  plt <- df %>% 
    filter(chrom == chr) %>% 
    filter(sample %in% trisomics) %>% 
    filter(binsize >= 2.5e5) %>% 
    ggplot(., aes(x = start, y = normcov, fill = sample)) +
    geom_line(aes(color = sample), size = 1) +
    geom_line(data = filter(df, chrom == chr & !sample %in% trisomics & binsize >= 2.5e5), aes(x = start, y = normcov, fill = sample), alpha = 0.2, size = 0.5) +
    facet_wrap(~chrom, strip.position = "r") +
    scale_x_continuous(breaks = seq(0,8e7,by=2e7), labels = seq(0,80,by=20)) +
    guides(fill = F, color = F) +
    labs(x = "Position (Mb)", y = "Standardized\nCoverage") +
    theme_bw() +
      theme(
      panel.grid.minor.x = element_blank(),
      panel.grid.minor.y = element_blank(),
      panel.grid.major.y = element_line(color="gray30", size = 0.2),
      panel.grid.major.x = element_blank(),
      strip.background = element_rect(fill = "white", color = "black"),
      panel.background = element_rect(fill = "white", color = "black"),
      axis.text = element_text(size = 14),
      axis.title = element_text(size = 16),
      strip.text = element_text(size = 14))
  # return(plt)
  print(plt)
  # ggsave(paste(chr, "_dosage_overlay.pdf", plot = plt, width = 6, height = 2, units = "in", device = "pdf")) # save these if needed
}
fig3a <- chrom_overlay(bin_dosage, "chr01") + ggtitle("A")

Last part, do high coverage CNV here to finish Fig. S3

sc
[1]  80.67005  89.43656  71.43014 110.69950

fig_4d <- chrom_overlay(bin_dosage, "chr06") + ggtitle("D")
Ignoring unknown aesthetics: fill

fig_4d

fig4 <- grid.arrange(fig_4a, fig_4b, fig_4c, fig_4d, nrow = 4)
ggsave("Fig4.png", plot = fig4, width = 12, height = 12, units = "in", device = "png")
ggsave("Fig4.pdf", plot = fig4, width = 12, height = 12, units = "in", device = "pdf")
for (i in sprintf('chr%02d', 1:12)) {
  plt <- chrom_overlay(bin_dosage, i)
  dplt <- dp %>% 
  filter(chrom == i) %>% 
  filter(N_content <= 0.3) %>% 
  filter(sample == "4x_LOP868") %>% 
  ggplot(., aes(x = start, y = gc_norm_dp)) + 
  geom_point(alpha = 0.3, size = 0.8) +
  labs(x = "", y = "Alca Tarma\nCopy Number") +
  # ggtitle("A") +
  scale_y_continuous(limits = c(0, 220), breaks = c(0, sc[4]*.25, sc[4]*.5, sc[4]*0.75, sc[4], sc[4]*1.25, sc[4]*1.5, sc[4]*1.75, sc[4]*2), labels = c(0,1,2,3,4,5,6,7,8)) +
  scale_x_continuous(limits = c(0,6e7), breaks = seq(0, 6e7, by = 2e7), labels = seq(0, 60, by = 20)) +
  facet_wrap(~chrom, nrow = 12, strip.position = "right") +
  theme(
    panel.grid.major.x = element_blank(),
    panel.grid.minor.x = element_blank(),
    panel.grid.major.y = element_line(color = "gray30", size = 0.2),
    panel.grid.minor.y = element_blank(),
    panel.background = element_rect(fill = "white", color = "black"),
    axis.text = element_text(size = 14),
    axis.title = element_text(size = 16),
    strip.text = element_text(size = 14),
    # plot.title = element_text(size = 24, face = "bold"),
    strip.background = element_rect(fill = "white", color = "black")
  )
  comb <- grid.arrange(dplt,plt)
  ggsave(paste0(i,"_figS3_combo_plot.png"), plot = comb, width = 9, height = 4, units = "in", device = "png")
}
Ignoring unknown aesthetics: fill

Fig. S5

names(sc) <- str_extract(dp_files, "LOP.+") %>%
  str_replace(., ".tsv", "") %>% 
  str_replace(., "_", ".")
names(sc)
overlay_emphasize_one <- function(df, dihap, chr) {
  plt <- df %>%
    filter(chrom == chr) %>% 
    filter(sample != dihap) %>% 
    filter(binsize >= 2.5e5) %>%
    ggplot(., aes(x = start, y = normcov, fill = sample)) +
    geom_line(alpha = 0.2) +
    geom_line(data = filter(df, chrom == chr & sample == dihap & binsize >= 2.5e5), color = "red", size = 1.2) +
    scale_x_continuous(breaks = seq(0,6e7,by=2e7), labels=seq(0,60,by=20)) +
    facet_wrap(~chrom, strip.position = "r") +
    labs(x = "Position (Mb)", y = "Standardized Coverage") +
    theme_bw() +
    theme(strip.background = element_rect(fill = "white", color = "black"),
          axis.text = element_text(size = 14),
          axis.title = element_text(size = 16),
          strip.text = element_text(size = 14),
          panel.grid.major.x = element_blank(),
          panel.grid.minor = element_blank())
  return(plt)
}
hicov <- function(df, dihap, chr, s, e) {
  
  sc_to_use <- dihap %>% 
    str_remove("[24]x_") %>% 
    str_replace(., "_", ".")
  # print(sc_to_use)
  
  sc_loc <- sc[which(names(sc) == sc_to_use)]
  
  plt <- df %>% 
    filter(chrom == chr) %>% 
    filter(between(start, s, e)) %>% 
    filter(N_content <= 0.3) %>% 
    filter(sample == dihap) %>% 
    ggplot(., aes(x = start, y = gc_norm_dp)) +
    # geom_point() +
    # geom_line() +
    labs(x = "Position (Mb)", y = paste(sc_to_use, "Copy Number", sep = " ")) +
    facet_wrap(~chrom, strip.position = "r") +
    scale_x_continuous(breaks = seq(s,e, by = 2.5e5), labels = seq(s/1e6, e/1e6, by = 0.25)) +
    scale_y_continuous(limits = c(0, 2*sc_loc), breaks = c(0, 0.5*sc_loc, sc_loc, 1.5*sc_loc, 2*sc_loc), labels = seq(0,4)) +
    theme_bw() +
    theme(strip.background = element_rect(fill = "white", color = "black"),
          axis.text = element_text(size = 14),
          axis.title = element_text(size = 16),
          strip.text = element_text(size = 14),
          panel.grid.major.x = element_blank(),
          panel.grid.minor = element_blank())
  return(plt)
}
s5_1 <- overlay_emphasize_one(bin_dosage, "2x_LOP868_004", "chr06")
s5_2 <- overlay_emphasize_one(bin_dosage, "2x_LOP868_064", "chr06")
s5_3 <- overlay_emphasize_one(bin_dosage, "2x_LOP868_305", "chr06")
s5_4 <- hicov(dp, "2x_LOP868_004", "chr06", 3.2e7, 3.4e7) + geom_point() + geom_line()
s5_5 <- hicov(dp, "2x_LOP868_064", "chr06", 3.2e7, 3.4e7) + geom_point() + geom_line()
s5_6 <- hicov(dp, "2x_LOP868_305", "chr06", 3.2e7, 3.4e7) + geom_point() + geom_line()
s5_7 <- hicov(dp, "2x_LOP868_004", "chr06", 0, 6e7) + geom_point(alpha = 0.3, size = 0.8) + scale_x_continuous(limits = c(0, 6e7), breaks = seq(0, 6e7, by = 2e7), labels = seq(0, 60, by = 20))
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
s5_8 <- hicov(dp, "2x_LOP868_064", "chr06", 0, 6e7) + geom_point(alpha = 0.3, size = 0.8) + scale_x_continuous(limits = c(0, 6e7), breaks = seq(0, 6e7, by = 2e7), labels = seq(0, 60, by = 20))
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
s5_9 <- hicov(dp, "2x_LOP868_305", "chr06", 0, 6e7) + geom_point(alpha = 0.3, size = 0.8) + scale_x_continuous(limits = c(0, 6e7), breaks = seq(0, 6e7, by = 2e7), labels = seq(0, 60, by = 20))
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.

Fig S4: Kernel density estimator plots illlustrating dosage variant clustering to get genotypes Note, red points were drawn in as manual points, using x values specified according to the cluster center, and the Y axis point drawn s/t it was at the peak of the kernel density function.

kde_bin <- function(df, chr, s) {
  active_bin <- filter(df, chrom == chr & start == s) %>% 
    mutate(bin = paste(chrom, start, end, sep = "_")) 
  plt <- ggplot(active_bin, aes(x = normcov)) +
    geom_histogram(aes(y = ..density..), binwidth = 0.1, fill = "blue", alpha = 0.5) +
    geom_density(kernel = "ep", bw = quantile(dist(active_bin$normcov), 0.4)) +
    scale_x_continuous(limits = c(0,4)) +
    facet_wrap(~bin, strip.position = "r")
  return(plt)
}
s4_1 <- kde_bin(bin_dosage, "chr01", 4.25e6)
s4_2 <- kde_bin(bin_dosage, "chr01", 2.425e7)
s4_3 <- kde_bin(bin_dosage, "chr01", 7.95e7)
ggsave("Fig_S4_1.png", plot = s4_1, width = 4, height = 2, units = "in", device = "png")
ggsave("Fig_S4_2.png", plot = s4_2, width = 4, height = 2, units = "in", device = "png")
ggsave("Fig_S4_3.png", plot = s4_3, width = 4, height = 2, units = "in", device = "png")

Fig. S6: Power analysis of rare indels in LOP dihaploid population. Note, I added the figure legend in Affinity Designer by copying the legend from figure s6_legend

simhyb_les_alleles <- read_tsv("../experiments/3_fake_hybrids/indel_bin_alleles_simhyb.txt", col_names = T) %>% 
  mutate(control_group = ifelse(grepl("SRR6123031", sample), "Simulated Alca Tarma x PL4",
                                ifelse(grepl("SRR6123183", sample), "Simulated Alca Tarma x IVP101", "Simulated Matrilineal"))) %>% 
  mutate(control_group = factor(control_group, levels = c("Simulated Matrilineal", "Simulated Alca Tarma x IVP101", "Simulated Alca Tarma x PL4"))) %>% 
  mutate(bin = paste(chrom, as.integer(start), as.integer(end), sep = "_"))
Parsed with column specification:
cols(
  chrom = col_character(),
  start = col_double(),
  end = col_double(),
  size = col_double(),
  sample = col_character(),
  PercALesion = col_double(),
  TotalCovLesion = col_double(),
  NumSNPLesion = col_double(),
  PercANotLesion = col_double(),
  TotalCovNotLesion = col_double(),
  NumSNPNotLesion = col_double()
)
head(simhyb_les_alleles)
plot_power_simhyb_lesion <- function(df, chr, s) {
  plt <- df %>% 
    filter(chrom == chr) %>% 
    filter(start == s) %>% 
    ggplot(., aes(x = PercALesion, fill = control_group)) +
    geom_histogram(binwidth = 0.01, alpha = 0.8) +
    labs(x = "Percent HI Allele", y = "Count") +
    facet_wrap(~bin) +
    theme_bw() +
    # guides(fill = F) +
    scale_x_continuous(limits = c(-0.01,1)) +
    scale_fill_manual(values = c("#00BA38", "#F8766D", "#00BFC4")) +
    theme(panel.grid = element_blank(),
          axis.text = element_text(size = 14),
          axis.title = element_text(size = 16),
          strip.text = element_text(size = 14),
          strip.background = element_rect(fill = "white", color = "black"))
  return(plt)
}

Fig. S2: Binned SNP result, including simulated hybrid power test.

melt_bin_alleles <- function(x) {
  df <- read_tsv(x, na = ".")
  
  ObsHI <- df %>% 
    select(Chrom,Start,End,Max,matches("Obs%A$")) %>% 
    mutate(chrbin = floor(Start/df$End[1])) %>% 
    gather(Ind, ObsPerHI, -Chrom, -Start, -End, -Max, -chrbin) %>% 
    mutate(Ind = str_replace_all(Ind, "v-(.+)-Obs%A", "\\1"))
  
  CalcHI <- df %>% 
    select(Chrom, Start, End, Max, matches('Calc%A$')) %>% 
    mutate(chrbin = floor(Start/df$End[1])) %>% 
    gather(Ind, CalcPerHI, -Chrom, -Start, -End, -Max, -chrbin) %>% 
    mutate(Ind = str_replace_all(Ind, "v-(.+)-Calc%A", "\\1")) 
  
  Cov <- df %>% 
    select(Chrom, Start, End, Max, matches('Cov$')) %>% 
    mutate(chrbin = floor(Start/df$End[1])) %>% 
    gather(Ind, Cov, -Chrom, -Start, -End, -Max, -chrbin) %>% 
    mutate(Ind = str_replace_all(Ind, "v-(.+)-Cov", "\\1"))
  
  df2 <- ObsHI %>% 
    inner_join(.,Cov) %>% 
    mutate(HIcalls = round(Cov * ObsPerHI / 100)) %>% 
    filter(Chrom != "chr00") %>% 
    # filter(!grepl("sub", Ind)) %>% 
    mutate(prenducer = str_extract(Ind, "(SRR6123031)|(SRR6123183)")) %>% 
    mutate(Inducer = ifelse(prenducer == "SRR6123031", "PL4", NA)) %>% 
    mutate(Inducer = ifelse(prenducer == "SRR6123183", "IVP101", Inducer)) %>% 
    mutate(ObsPerHI_filt = ifelse(Cov >= 10, ObsPerHI, NA)) %>% 
    mutate(start_cen = Start + (End-Start)/2) 
  print(head(df2))
  
  return(df2)
}
big <- melt_bin_alleles("../experiments/3_fake_hybrids/1Mb_bin_alleles_simhyb.txt") %>% 
  mutate(`Control Group` = ifelse(Inducer == "PL4", "Simulated Alca Tarma x PL4", ifelse(Inducer == "IVP101", "Simulated Alca Tarma x IVP101", "Simulated Matrilineal")))
Parsed with column specification:
cols(
  .default = col_double(),
  Chrom = col_character()
)
See spec(...) for full column specifications.
Joining, by = c("Chrom", "Start", "End", "Max", "chrbin", "Ind")
pc <- big %>% 
  filter(grepl("SRR6123031|SRR6123183", Ind))
nc <- big %>% 
  filter(grepl("uniparental", Ind))
# Define bins
bigp <- big %>% 
  select(Chrom, Start, End) %>% 
  distinct() %>% 
  mutate(overlap_test = NA) %>% 
  mutate(missing_n_test = NA) %>%
  mutate(missing_n_frac = NA) %>% 
  mutate(missing_p_test = NA) %>% 
  mutate(missing_p_frac = NA)
nrow(bigp)
[1] 730
# define critical fraction of missing data
nafrac_crit <- 0.05 # may have to futz with this
for (i in 1:nrow(bigp)) {
  
  chrom <- bigp$Chrom[i]
  strt <- bigp$Start[i]
  endd <- bigp$End[i]
  
  # Define range of values for bin in negative control population
  rng_p <- pc %>% 
    filter(Chrom == chrom) %>% 
    filter(Start == strt) %>% 
    filter(End == endd) %>% 
    select(ObsPerHI)
  
  pmin <- min(rng_p$ObsPerHI, na.rm = T)
  print(paste("pmin:", pmin))
  
  pmax <- max(rng_p$ObsPerHI, na.rm = T)
  print(paste("pmax:", pmax))
  
  nafrac_p <- sum(is.na(rng_p$ObsPerHI)) / length(rng_p$ObsPerHI)
  
  # Define range of values for bin in positive control population
  rng_n <- nc %>% 
    filter(Chrom == chrom) %>% 
    filter(Start == strt) %>% 
    filter(End == endd) %>% 
    select(ObsPerHI)
  
  nmin <- min(rng_n$ObsPerHI, na.rm = T)
  print(paste("nmin:", nmin))
  
  nmax <- max(rng_n$ObsPerHI, na.rm = T)
  print(paste("nmax:", nmax))
  
  nafrac_n <- sum(is.na(rng_n$ObsPerHI)) / length(rng_n$ObsPerHI)
  
  # Define PASS/FAIL criteria as variables in original data frame
  # first failure criterion: if max of negative control greater than min of positive control
  bigp$overlap_test[i] = ifelse(nmax >= pmin, "FAIL", "PASS") # can then cbind when I'm done.
  
  # second failture criterion: missing data in negative control
  bigp$missing_n_test[i] <- ifelse(nafrac_n >= nafrac_crit, "FAIL", "PASS")
  bigp$missing_n_frac[i] <- nafrac_n
  
  # third failure criterion: missing data in positive control
  bigp$missing_p_test[i] <- ifelse(nafrac_p >= nafrac_crit, "FAIL", "PASS")
  bigp$missing_p_frac[i] <- nafrac_p
}
qc_bins <- left_join(pc, bigp) %>% 
  mutate(ObsPerHI_qc = ifelse(overlap_test == "PASS", ObsPerHI, NA))
Joining, by = c("Chrom", "Start", "End")
real <- melt_bin_alleles("../experiments/4_low_cov_snp/1Mb_bin_alleles_LOP.txt")
Parsed with column specification:
cols(
  .default = col_double(),
  Chrom = col_character()
)
See spec(...) for full column specifications.
Joining, by = c("Chrom", "Start", "End", "Max", "chrbin", "Ind")
real3 <- real %>% 
  filter(!(Ind %in% c("2x_IVP_101", "2x_PL_4", "4x_LOP868", "2x_LOP868_279"))) %>% 
  filter(Chrom != "chr00") %>% 
  left_join(., bigp) %>% 
  mutate(ObsPerHI_qc = ifelse(overlap_test == "PASS", ObsPerHI, NA)) %>% 
  mutate(ObsPerHI_qc_cov = ifelse(Cov < 30, NA, ObsPerHI_qc)) %>% 
  mutate(ObsPerHI_qc_50cov = ifelse(Cov < 50, NA, ObsPerHI_qc))
Joining, by = c("Chrom", "Start", "End")
fig_s2 <- real3 %>% 
  ggplot(., aes(x = Start, y = ObsPerHI_qc_cov, fill = Ind)) +
  geom_line(size = 0.5, alpha = 0.5) +
  geom_line(data = qc_bins, aes(x = Start, y = ObsPerHI_qc, fill = Ind, color = `Control Group`), size = 0.2, alpha = 0.3) +
  facet_wrap(~Chrom, nrow = 6, strip.position = "r") +
  labs(x = "Position (Mb)", y = "%HI SNPs") +
  scale_x_continuous(limits = c(0,8e7), breaks = seq(0,8e7,by=2e7), labels=seq(0,80,by=20)) +
  scale_y_continuous(limits = c(0,100)) +
  # scale_color_manual(values = c("#00BA38", "#619CFF", "#F8766D")) +
  theme_bw() +
  theme(panel.grid.minor = element_blank(),
        panel.grid.major.x = element_blank(),
        panel.grid.major.y = element_line(linetype = "dotted"),
        legend.position = "bottom",
        axis.text = element_text(size = 14),
        axis.title = element_text(size = 16),
        strip.text = element_text(size = 14))
Ignoring unknown aesthetics: fill
fig_s2
ggsave("Fig_S2.png", width = 10, height = 10, units = "in", device = "png", plot = fig_s2)
ggsave("Fig_S2.pdf", width = 10, height = 10, units = "in", device = "pdf", plot = fig_s2)

Overlay combined dosage and 1Mb SNP plots for Fig. S1. These were later put together in Affinity Designer with metaphase spreads, if spreads were available. TODO: put raw images of spreads in a separate folder.

numblanks_snp <- 10
mid <- function(x) {
  n = floor(nrow(x)/2)
  return(x$bin[n])
}
plot.snp <- function(x,y,z) {
  keep <- real3 %>% 
    filter(Ind == x) %>% 
    select(Chrom, Start, End, Max, chrbin, Ind, ObsPerHI, Cov, HIcalls, ObsPerHI_qc_cov)
    
  keep$bin <- seq(1:nrow(keep))
  # print(head(keep))
  
  stuf <- c(rep(NA, numblanks_snp))
  stuffer <- data.frame("Chrom"=stuf,
                        "Start"=stuf,
                        "End"=stuf,
                        "Max"=stuf,
                        "chrbin"=stuf,
                        "Ind"=stuf,
                        "ObsPerHI"=stuf,
                        "Cov"=stuf,
                        "HIcalls"=stuf,
                        "ObsPerHI_qc_cov"=stuf,
                        "bin"=stuf)
  chr.list <- split(keep, f=keep$Chrom)
  chr.list.stuffed <- lapply(chr.list[1:11], function(x) rbind(x,stuffer))
  ind.mod <- bind_rows(chr.list.stuffed, chr.list[[12]])
  ind.mod$bin2 <- seq(1:nrow(ind.mod))
  
  midpoints <- sapply(chr.list[1:12], mid)
  if (z == T) {
    x.axis.breaks <- which(ind.mod$bin %in% midpoints)
    x.axis.labels <- names(midpoints)
  } else {
    x.axis.breaks <- seq(1,12)
    x.axis.labels <- rep("",12)
  }
    plt.ind.JMPlike <- ggplot(ind.mod, aes(x=bin2,y=ObsPerHI_qc_cov)) +
    labs(x="", y="% HI SNPs") +
    ggtitle(" ") +
    # geom_line(y=0.0, color="black", linetype="dashed", size = 2) +
    # geom_line(y = 33/4, color = "black", linetype = "dashed") +
    geom_line(color=y, fill=NULL,size=3) +
    scale_color_manual(values=c(rep(y,12))) +
    theme(panel.grid.minor.x = element_blank(),
          panel.grid.minor.y=element_blank(),
          panel.grid.major.x = element_blank(),
          panel.grid.major.y = element_line(color="black", linetype="dashed"),
          panel.background = element_rect(fill="white",color="black"),
          axis.text.x = element_text(size=18, color="black"),
          axis.text.y=element_text(size=18,color="black"),
          axis.title.y=element_text(size=18, angle=90, vjust = 0.5, margin = margin(t = 0, r = 25, b = 0, l = 0)),
          axis.ticks = element_blank(),
          plot.title=element_text(size=24,face="bold",hjust=0),
          panel.border = element_rect(color = "black", fill = NA, size = 2)) +
    geom_point(size = 2.0,color="black") +
    guides(fill=FALSE, color=FALSE) +
    scale_y_continuous(limits=c(-5,100), breaks=c(100,66,33,0)) +
    scale_x_continuous(breaks=x.axis.breaks, labels=x.axis.labels)
  plt.ind.JMPlike
}
# retrieves midpoints of each chromosome
mid.dosage <- function(x) {
  n=floor(nrow(x)/2)
  return(x$bin[n])
}
# Dosage plot function arguments:
# x is the name of the .tsv fle to be read in
# y is the title of the plot. I gsub the string x to get the title. I could hard code this but I leave it as an arg to be more customizable.
plot.dosage <- function(ind, y) {
  todo <- which(names(all_dosage) == ind)
  # print(todo)
  
  plt.dosage <- all_dosage[[todo]] %>%
    ggplot(., aes(x = bin2, y = normcov)) +
    labs(x = "", y="Standardized\nCopy Number") +
    geom_line(color = "#008080", fill = "white", size = 3) +
    ggtitle(y) +
    geom_point(size = 2, color = "black") +
    guides(fill = F, color = F) +
    scale_y_continuous(limits = c(0,5), breaks = seq(0,5), labels = seq(0,5)) +
    theme(panel.grid.minor.x = element_blank(),
          panel.grid.minor.y=element_blank(),
          panel.grid.major.x = element_blank(),
          panel.grid.major.y = element_line(color="black", linetype="dashed"),
          panel.background = element_rect(fill="white",color="black"),
          axis.text.x = element_blank(),
          axis.text.y=element_text(size=18,color="black"),
          axis.title.y=element_text(size=18, angle=90, vjust = 0.5, margin = margin(t = 0, r = 25, b = 0, l = 0)),
          axis.ticks = element_blank(),
          plot.title=element_text(size=24,face="bold",hjust=0),
          panel.border = element_rect(fill = NA, color = "black", size = 2))
  plt.dosage
}
plot.dosage("2x_LOP868_064", "LOP868.064")
Ignoring unknown parameters: fill

plot.snp("2x_LOP868_004", "#008080", TRUE)
Ignoring unknown parameters: fill

stack.plot <- function(x) {
  # dosage.fh <- gsub("$", "-dosage_plot.tsv", x)
  # dosage <- read.table(dosage.fh, header=T)
  gt <- ggplotGrob(plot.dosage(x, ""))
  gb <- ggplotGrob(plot.snp(x, "#008080", TRUE))
  fig.s1.template <- rbind(gt,gb, size = "first")
  fig.s1.template$widths <- unit.pmax(gt$widths)
  fig.s1.template$layout[grepl("guide", fig.s1.template$layout$name), c("t", "b")] <- c(1, nrow(fig.s1.template))
  grid.newpage()
  grid.draw(fig.s1.template)
  # out.fh <- gsub("^", "2018_0531_", i)
  out.fh <- gsub("$", "_stack_plot.eps", x)
  ggsave(out.fh, plot=fig.s1.template, width = 24, height = 6, units = "in", device = "eps") # 18 inch width for supplemental figures, 24 inch width for main
}
for (i in names(all_dosage)) {
  stack.plot(i)
}
Ignoring unknown parameters: fillRemoved 497 rows containing missing values (geom_point).Ignoring unknown parameters: fillRemoved 1 rows containing missing values (geom_path).Removed 249 rows containing missing values (geom_point).

Circos plot generation done in a subdirectory of results

LS0tCnRpdGxlOiAiTE9QIE1hbnVzY3JpcHQgRmlndXJlcyIKYXV0aG9yOiAiS2lyayBBbXVuZHNvbiIKZGF0ZTogMjAxOV8xMDEyCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShncmlkKQpsaWJyYXJ5KGdyaWRFeHRyYSkKYGBgCgpgYGB7cn0KZmlsZXMgPC0gZGlyKHBhdGggPSAiLi4vZXhwZXJpbWVudHMvMl9sb3dfY292X2Nudi9kYXRhL3Bsb3RzIiwgcGF0dGVybiA9ICItZG9zYWdlX3Bsb3QudHN2IiwgZnVsbC5uYW1lcyA9IFQpCmZpbGVzCmBgYAoKYGBge3J9Cm5hbWVzKGFsbF9kb3NhZ2UpIDwtIHN0cl9leHRyYWN0KGZpbGVzLCAiWzI0XXhfLisiKSAlPiUgCiAgc3RyX3JlbW92ZSgiLWRvc2FnZV9wbG90LnRzdiIpCm5hbWVzKGFsbF9kb3NhZ2UpCmBgYAoKCmBgYHtyfQphbGxfZG9zYWdlIDwtIGZpbGVzICU+JSAKICBtYXAocmVhZF9kZWxpbSwgZGVsaW0gPSAiICIsIGNvbF9uYW1lcyA9IFQpCiAgCmZvciAoaSBpbiAxOmxlbmd0aChmaWxlcykpIHsKICBhbGxfZG9zYWdlW1tpXV0kc2FtcGxlIDwtIHN0cl9yZXBsYWNlKGZpbGVzW2ldLCAiLi4vZXhwZXJpbWVudHMvMl9sb3dfY292X2Nudi9kYXRhL3Bsb3RzLyIsICIiKQogIGFsbF9kb3NhZ2VbW2ldXSRzYW1wbGUgPC0gZ3N1YigiLWRvc2FnZV9wbG90LnRzdiIsICIiLCBhbGxfZG9zYWdlW1tpXV0kc2FtcGxlKQogIGFsbF9kb3NhZ2VbW2ldXSRzYW1wbGVfbnVtIDwtIGkKfQoKYmluX2Rvc2FnZSA8LSBhbGxfZG9zYWdlICU+JSAKICBiaW5kX3Jvd3MoKSAlPiUgCiAgbXV0YXRlKHNhbXBsZSA9IHN0cl9yZXBsYWNlKHNhbXBsZSwgIi1kb3NhZ2VfcGxvdC50c3YiLCAiIikpICU+JSAKICBmaWx0ZXIoc2FtcGxlICE9ICIyeF9MT1A4NjhfMjc5IikKCmNocm9tX2Rvc2FnZSA8LSBiaW5fZG9zYWdlICU+JSAKICBncm91cF9ieShjaHJvbSwgc2FtcGxlLCBzYW1wbGVfbnVtKSAlPiUgCiAgc3VtbWFyaXplKGNocm9tX3JlYWRjb3VudCA9IHN1bShyZWFkY291bnQpKSAlPiUgCiAgYXJyYW5nZShzYW1wbGUsIGNocm9tKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShjaHJvbSkpICU+JSAKICB1bmdyb3VwKCkKYGBgCgpgYGB7cn0Kd2l0aF90b3RhbHMgPC0gY2hyb21fZG9zYWdlICU+JSAKICBncm91cF9ieShzYW1wbGUsIHNhbXBsZV9udW0pICU+JSAKICBzdW1tYXJpemUodG90YWxfcmVhZGNvdW50ID0gc3VtKGNocm9tX3JlYWRjb3VudCkpICU+JSAKICBsZWZ0X2pvaW4oY2hyb21fZG9zYWdlLCAuKSAlPiUgCiAgdW5ncm91cCgpCmBgYAoKYGBge3J9CndpdGhfY29udHJvbCA8LSB3aXRoX3RvdGFscyAlPiUgCiAgZmlsdGVyKHNhbXBsZSA9PSAiNHhfTE9QODY4IikgJT4lIAogIG11dGF0ZShjaHJvbXNob3J0ID0gc3RyX3JlcGxhY2UoY2hyb20sICJjaHIiLCAiIikpICU+JSAKICBtdXRhdGUoY2hyb21zaG9ydCA9IHN0cl9yZXBsYWNlKGNocm9tc2hvcnQsICJeMCIsICIiKSkgJT4lIAogIHJlbmFtZShjb250cm9sX2Nocm9tX3JlYWRjb3VudCA9IGNocm9tX3JlYWRjb3VudCkgJT4lIAogIHJlbmFtZShjb250cm9sX3RvdGFsX3JlYWRjb3VudCA9IHRvdGFsX3JlYWRjb3VudCkgJT4lCiAgc2VsZWN0KC1zYW1wbGUsIC1zYW1wbGVfbnVtKSAlPiUgCiAgbGVmdF9qb2luKHdpdGhfdG90YWxzLCAuKSAlPiUgCiAgbXV0YXRlKG5vcm1jb3YgPSAyKiAoY2hyb21fcmVhZGNvdW50IC8gdG90YWxfcmVhZGNvdW50KSAvIChjb250cm9sX2Nocm9tX3JlYWRjb3VudCAvIGNvbnRyb2xfdG90YWxfcmVhZGNvdW50KSkgJT4lIAogIGZpbHRlcighc2FtcGxlICVpbiUgYygiNHhfTE9QODY4IiwgIjJ4X0xPUDg2OF8yNzkiKSkKYGBgCgpgYGB7cn0KZmlnMkEgPC0gd2l0aF9jb250cm9sICU+JSAKICBmaWx0ZXIobm9ybWNvdiA8PSBtZWFuKHdpdGhfY29udHJvbCRub3JtY292ICsgMypzZCh3aXRoX2NvbnRyb2wkbm9ybWNvdikpKSAlPiUgCiAgZ2dwbG90KC4sIGFlcyh4ID0gc2FtcGxlX251bSwgeSA9IG5vcm1jb3YpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYyh3aXRoX2NvbnRyb2wkc2FtcGxlX251bVt3aGljaCh3aXRoX2NvbnRyb2wkbm9ybWNvdiA+PSBtZWFuKHdpdGhfY29udHJvbCRub3JtY292KSArIDMgKiBzZCh3aXRoX2NvbnRyb2wkbm9ybWNvdikpXSksIGNvbG9yID0gImdyYXk3MCIpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdGV4dChkYXRhID0gZmlsdGVyKHdpdGhfY29udHJvbCwgbm9ybWNvdiA+PSBtZWFuKHdpdGhfY29udHJvbCRub3JtY292KSArIDMqc2Qod2l0aF9jb250cm9sJG5vcm1jb3YpKSwgYWVzKHggPSBzYW1wbGVfbnVtLCB5ID0gbm9ybWNvdiwgbGFiZWwgPSBjaHJvbXNob3J0KSwgc2l6ZSA9IDUsIGZvbnRmYWNlID0gImJvbGQiKSArCiAgZ2VvbV9saW5lKHkgPSBtZWFuKHdpdGhfY29udHJvbCRub3JtY292KSwgY29sb3IgPSAiZ3JlZW4iKSArCiAgZ2VvbV9saW5lKHkgPSBtZWFuKHdpdGhfY29udHJvbCRub3JtY292KSArIDMgKiBzZCh3aXRoX2NvbnRyb2wkbm9ybWNvdiksIGNvbG9yID0gInJlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygxLDE2NyksIGxhYmVscyA9IGMoIjEiLCAiMTY3IikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygxLjYsIDMuMykpICsKICBnZ3RpdGxlKCJBIikgKwogIGxhYnMoeCA9ICJJbmRpdmlkdWFsIiwgeSA9ICJDaHJvbW9zb21lXG5Db3B5IE51bWJlciIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQ9ZWxlbWVudF9yZWN0KGZpbGw9IndoaXRlIixjb2xvcj0iYmxhY2siKSwKICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KHNpemU9MTgpLAogICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoc2l6ZT0xOCxhbmdsZT0gOTAsIHZqdXN0PTAuNSksIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MjQsZmFjZT0iYm9sZCIsaGp1c3Q9MCxjb2xvcj0iYmxhY2siKSwKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT0xOCxjb2xvcj0iYmxhY2siKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xOCxjb2xvcj0iYmxhY2siKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTcwIikpCmZpZzJBCiMgZ2dzYXZlKCJGaWcyQS5wZGYiLCBwbG90PWZpZzJBLCB3aWR0aCA9IDE4LCBoZWlnaHQgPSAzLCB1bml0cyA9ICJpbiIsIGRldmljZSA9ICJwZGYiKQpgYGAKCj4gVGhpcyBpcyBhIG1hdGhlbWF0aWNhbCByZXByZXNlbnRhdGlvbiBvZiB0cmlzb215LCBzbyBJIGNhbiB1c2UgdGhpcyB0byBnbyBiYWNrIGFuZCBtYWtlIG92ZXJsYXkgcGxvdHMKd2lodGhvdXQgaGF2aW5nIHRvIG1hbnVhbGx5IHNwZWNpZnkgdGhlbS4KCmBgYHtyfQp0cmlzb21pY3MgPC0gd2l0aF9jb250cm9sJHNhbXBsZVt3aGljaCh3aXRoX2NvbnRyb2wkbm9ybWNvdiA+PSBtZWFuKHdpdGhfY29udHJvbCRub3JtY292KSArIDMgKiBzZCh3aXRoX2NvbnRyb2wkbm9ybWNvdikpXQpgYGAKCmBgYHtyfQpjaHJvbV9vdmVybGF5IDwtIGZ1bmN0aW9uKGRmLCBjaHIpIHsKICBwbHQgPC0gZGYgJT4lIAogICAgZmlsdGVyKGNocm9tID09IGNocikgJT4lIAogICAgZmlsdGVyKHNhbXBsZSAlaW4lIHRyaXNvbWljcykgJT4lIAogICAgZmlsdGVyKGJpbnNpemUgPj0gMi41ZTUpICU+JSAKICAgIGdncGxvdCguLCBhZXMoeCA9IHN0YXJ0LCB5ID0gbm9ybWNvdiwgZmlsbCA9IHNhbXBsZSkpICsKICAgIGdlb21fbGluZShhZXMoY29sb3IgPSBzYW1wbGUpLCBzaXplID0gMSkgKwogICAgZ2VvbV9saW5lKGRhdGEgPSBmaWx0ZXIoZGYsIGNocm9tID09IGNociAmICFzYW1wbGUgJWluJSB0cmlzb21pY3MgJiBiaW5zaXplID49IDIuNWU1KSwgYWVzKHggPSBzdGFydCwgeSA9IG5vcm1jb3YsIGZpbGwgPSBzYW1wbGUpLCBhbHBoYSA9IDAuMiwgc2l6ZSA9IDAuNSkgKwogICAgZmFjZXRfd3JhcCh+Y2hyb20sIHN0cmlwLnBvc2l0aW9uID0gInIiKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsOGU3LGJ5PTJlNyksIGxhYmVscyA9IHNlcSgwLDgwLGJ5PTIwKSkgKwogICAgZ3VpZGVzKGZpbGwgPSBGLCBjb2xvciA9IEYpICsKICAgIGxhYnMoeCA9ICJQb3NpdGlvbiAoTWIpIiwgeSA9ICJTdGFuZGFyZGl6ZWRcbkNvdmVyYWdlIikgKwogICAgdGhlbWVfYncoKSArCiAgICAgIHRoZW1lKAogICAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG9yPSJncmF5MzAiLCBzaXplID0gMC4yKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpLAogICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpLAogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpCiAgcmV0dXJuKHBsdCkKICAjIHByaW50KHBsdCkKICAjIGdnc2F2ZShwYXN0ZShjaHIsICJfZG9zYWdlX292ZXJsYXkucGRmIiwgcGxvdCA9IHBsdCwgd2lkdGggPSA2LCBoZWlnaHQgPSAyLCB1bml0cyA9ICJpbiIsIGRldmljZSA9ICJwZGYiKSkgIyBzYXZlIHRoZXNlIGlmIG5lZWRlZAp9CmBgYAoKYGBge3J9CmZpZzNhIDwtIGNocm9tX292ZXJsYXkoYmluX2Rvc2FnZSwgImNocjAxIikgKyBnZ3RpdGxlKCJBIikKYGBgCgpMYXN0IHBhcnQsIGRvIGhpZ2ggY292ZXJhZ2UgQ05WIGhlcmUgdG8gZmluaXNoIEZpZy4gUzMKCmBgYHtyfQojIGRwcyA8LSBkaXIocGF0aCA9ICIuLi8uLiIpCmRwX2NvbHMgPC0gYygiY2hyb20iLCAic3RhcnQiLCAiZW5kIiwgIm1lYW5fZHAiLCAibWVkaWFuX2RwIikKZHBfZmlsZXMgPC0gZGlyKHBhdHRlcm4gPSAic3VtbWFyaXplZC1kZXB0aCIsIHBhdGggPSAiLi4vZXhwZXJpbWVudHMvMV9oaWdoX2Nvdl92YXJpYW50cy9kYXRhL21lcmdlZC8iLCBmdWxsLm5hbWVzID0gVCkKCmRwIDwtIGRwX2ZpbGVzICU+JSAKICBtYXAocmVhZF90c3YsIGNvbF9uYW1lcyA9IGRwX2NvbHMpCgpzYyA8LSByZXAoTkEsIGxlbmd0aChkcF9maWxlcykpCmZvciAoaSBpbiAxOmxlbmd0aChkcF9maWxlcykpIHsKICBkcFtbaV1dIDwtIGxlZnRfam9pbihkcFtbaV1dLCByZWFkX3RzdigiLi4vZXhwZXJpbWVudHMvcmVmL0dDTl8xMGtfYmluX3BvdGF0b19kbV92NDA0X2FsbF9wbV91bl9jaGxvcm9fbWl0by5mYXN0YSIsIGNvbF9uYW1lcyA9IFQpKQogIGRwW1tpXV0kc2FtcGxlIDwtIHN0cl9leHRyYWN0KGRwX2ZpbGVzW2ldLCAiWzAtOV14X0xPUDg2OC4rIikKICBkcFtbaV1dJGdjX25vcm1fZHAgPC0gZHBbW2ldXSRtZWRpYW5fZHAgLyBkcFtbaV1dJEdDX2NvbnRlbnQKICBzZXQuc2VlZCg1KQogIG10eCA8LSB0KG1hdHJpeChkYXRhID0gYyhzYW1wbGUobmEub21pdChkcFtbaV1dJGdjX25vcm1fZHApLCAxMDAwKSwgcmVwKDAsMTAwMCkpLCBuY29sPTIpKQogIGNsdXN0ZXJzIDwtIG1zQ2x1c3RlcmluZyhtdHgsIGtlcm5lbCA9ICJlcGFuZWNobmlrb3ZLZXJuZWwiLCBoPSBxdWFudGlsZShkaXN0KG10eFsxLF0pLCAwLjI1KSkKICBzY1tpXSA8LSBjbHVzdGVycyRjb21wb25lbnRzWzEsMV0KfQoKZHAgPC0gZHAgJT4lCiAgYmluZF9yb3dzKCkgJT4lCiAgbXV0YXRlKHNhbXBsZSA9IHN0cl9yZW1vdmUoc2FtcGxlLCAiLnRzdiQiKSkKYGBgCgpgYGB7cn0KZmlnXzRhIDwtIGRwICU+JSAKICBmaWx0ZXIoY2hyb20gPT0gImNocjA2IikgJT4lIAogIGZpbHRlcihOX2NvbnRlbnQgPD0gMC4zKSAlPiUgCiAgZmlsdGVyKHNhbXBsZSA9PSAiNHhfTE9QODY4IikgJT4lIAogIGdncGxvdCguLCBhZXMoeCA9IHN0YXJ0LCB5ID0gZ2Nfbm9ybV9kcCkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMywgc2l6ZSA9IDAuOCkgKwogIGxhYnMoeCA9ICIiLCB5ID0gIkFsY2EgVGFybWEgQ29weSBOdW1iZXIiKSArCiAgZ2d0aXRsZSgiQSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAyMjApLCBicmVha3MgPSBjKDAsIHNjWzRdKi4yNSwgc2NbNF0qLjUsIHNjWzRdKjAuNzUsIHNjWzRdLCBzY1s0XSoxLjI1LCBzY1s0XSoxLjUsIHNjWzRdKjEuNzUsIHNjWzRdKjIpLCBsYWJlbHMgPSBjKDAsMSwyLDMsNCw1LDYsNyw4KSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsNmU3KSwgYnJlYWtzID0gc2VxKDAsIDZlNywgYnkgPSAyZTcpLCBsYWJlbHMgPSBzZXEoMCwgNjAsIGJ5ID0gMjApKSArCiAgZmFjZXRfd3JhcCh+Y2hyb20sIG5yb3cgPSAxMiwgc3RyaXAucG9zaXRpb24gPSAicmlnaHQiKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTMwIiwgc2l6ZSA9IDAuMiksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICAjIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI0LCBmYWNlID0gImJvbGQiKSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIikKICApCmBgYAoKYGBge3J9CmZpZ180YiA8LSBkcCAlPiUgCiAgZmlsdGVyKGNocm9tID09ICJjaHIwNiIpICU+JSAKICBmaWx0ZXIoc3RhcnQgPj0gMy4yZTcgJiBzdGFydCA8PSAzLjRlNykgJT4lCiAgZmlsdGVyKE5fY29udGVudCA8PSAwLjMpICU+JSAKICBmaWx0ZXIoc2FtcGxlID09ICI0eF9MT1A4NjgiKSAlPiUgCiAgZ2dwbG90KC4sIGFlcyh4ID0gc3RhcnQsIHkgPSBnY19ub3JtX2RwKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHggPSAiIiwgeSA9ICJBbGNhIFRhcm1hIENvcHkgTnVtYmVyIikgKwogIGdndGl0bGUoIkIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMjIwKSwgYnJlYWtzID0gYygwLCBzY1s0XSouMjUsIHNjWzRdKi41LCBzY1s0XSowLjc1LCBzY1s0XSwgc2NbNF0qMS4yNSwgc2NbNF0qMS41LCBzY1s0XSoxLjc1LCBzY1s0XSoyKSwgbGFiZWxzID0gYygwLDEsMiwzLDQsNSw2LDcsOCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDMuMmU3LCAzLjRlNywgYnkgPSAyLjVlNSksIGxhYmVscyA9IHNlcSgzMiwzNCxieT0wLjI1KSkgKwogIGZhY2V0X3dyYXAofmNocm9tLCBucm93ID0gMTIsIHN0cmlwLnBvc2l0aW9uID0gInJpZ2h0IikgKwogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXkzMCIsIHNpemUgPSAwLjIpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgIyBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNCwgZmFjZSA9ICJib2xkIiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpCiAgKQpmaWdfNGIKYGBgCgpgYGB7cn0KZmlnXzRjIDwtIGJpbl9kb3NhZ2UgJT4lIAogIGZpbHRlcihjaHJvbSA9PSAiY2hyMDYiICYgYmV0d2VlbihzdGFydCwgMy4yZTcsIDMuNGU3KSkgJT4lIAogIGdncGxvdCguLCBhZXMoeCA9IHN0YXJ0LCB5ID0gbm9ybWNvdikpICsKICBnZW9tX3F1YXNpcmFuZG9tKGFscGhhID0gMC44LCBzaXplID0gMC44KSArCiAgZ3VpZGVzKGNvbG9yID0gRikgKwogIGxhYnMoeCA9ICIiLCB5ID0gIlN0YW5kYXJkaXplZCBDb3ZlcmFnZSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDMuMmU3LDMuNGU3LGJ5PTIuNWU1KSwgbGFiZWxzPXNlcSgzMiwzNCxieT0wLjI1KSkgKwogIGZhY2V0X3dyYXAofmNocm9tLCBzdHJpcC5wb3NpdGlvbiA9ICJyIikgKwogIGdndGl0bGUoIkMiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICAjIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgdmp1c3QgPSAxKSwKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShjb2xvcj0iZ3JheTMwIiwgc2l6ZSA9IDAuMiksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpLAogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQpmaWdfNGMKYGBgCgpgYGB7cn0KZmlnXzRkIDwtIGNocm9tX292ZXJsYXkoYmluX2Rvc2FnZSwgImNocjA2IikgKyBnZ3RpdGxlKCJEIikKZmlnXzRkCmBgYAoKYGBge3J9CmZpZzQgPC0gZ3JpZC5hcnJhbmdlKGZpZ180YSwgZmlnXzRiLCBmaWdfNGMsIGZpZ180ZCwgbnJvdyA9IDQpCmdnc2F2ZSgiRmlnNC5wbmciLCBwbG90ID0gZmlnNCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gMTIsIHVuaXRzID0gImluIiwgZGV2aWNlID0gInBuZyIpCmdnc2F2ZSgiRmlnNC5wZGYiLCBwbG90ID0gZmlnNCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gMTIsIHVuaXRzID0gImluIiwgZGV2aWNlID0gInBkZiIpCmBgYAoKYGBge3J9CmZvciAoaSBpbiBzcHJpbnRmKCdjaHIlMDJkJywgMToxMikpIHsKICBwbHQgPC0gY2hyb21fb3ZlcmxheShiaW5fZG9zYWdlLCBpKQogIGRwbHQgPC0gZHAgJT4lIAogIGZpbHRlcihjaHJvbSA9PSBpKSAlPiUgCiAgZmlsdGVyKE5fY29udGVudCA8PSAwLjMpICU+JSAKICBmaWx0ZXIoc2FtcGxlID09ICI0eF9MT1A4NjgiKSAlPiUgCiAgZ2dwbG90KC4sIGFlcyh4ID0gc3RhcnQsIHkgPSBnY19ub3JtX2RwKSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gMC4zLCBzaXplID0gMC44KSArCiAgbGFicyh4ID0gIiIsIHkgPSAiQWxjYSBUYXJtYVxuQ29weSBOdW1iZXIiKSArCiAgIyBnZ3RpdGxlKCJBIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDIyMCksIGJyZWFrcyA9IGMoMCwgc2NbNF0qLjI1LCBzY1s0XSouNSwgc2NbNF0qMC43NSwgc2NbNF0sIHNjWzRdKjEuMjUsIHNjWzRdKjEuNSwgc2NbNF0qMS43NSwgc2NbNF0qMiksIGxhYmVscyA9IGMoMCwxLDIsMyw0LDUsNiw3LDgpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCw2ZTcpLCBicmVha3MgPSBzZXEoMCwgNmU3LCBieSA9IDJlNyksIGxhYmVscyA9IHNlcSgwLCA2MCwgYnkgPSAyMCkpICsKICBmYWNldF93cmFwKH5jaHJvbSwgbnJvdyA9IDEyLCBzdHJpcC5wb3NpdGlvbiA9ICJyaWdodCIpICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5MzAiLCBzaXplID0gMC4yKSwKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwKICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICMgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjQsIGZhY2UgPSAiYm9sZCIpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKQogICkKICBjb21iIDwtIGdyaWQuYXJyYW5nZShkcGx0LHBsdCkKICBnZ3NhdmUocGFzdGUwKGksIl9maWdTM19jb21ib19wbG90LnBuZyIpLCBwbG90ID0gY29tYiwgd2lkdGggPSA5LCBoZWlnaHQgPSA0LCB1bml0cyA9ICJpbiIsIGRldmljZSA9ICJwbmciKQp9CmBgYAoKRmlnLiBTNQoKYGBge3J9Cm5hbWVzKHNjKSA8LSBzdHJfZXh0cmFjdChkcF9maWxlcywgIkxPUC4rIikgJT4lCiAgc3RyX3JlcGxhY2UoLiwgIi50c3YiLCAiIikgJT4lIAogIHN0cl9yZXBsYWNlKC4sICJfIiwgIi4iKQpuYW1lcyhzYykKYGBgCgpgYGB7cn0Kb3ZlcmxheV9lbXBoYXNpemVfb25lIDwtIGZ1bmN0aW9uKGRmLCBkaWhhcCwgY2hyKSB7CiAgcGx0IDwtIGRmICU+JQogICAgZmlsdGVyKGNocm9tID09IGNocikgJT4lIAogICAgZmlsdGVyKHNhbXBsZSAhPSBkaWhhcCkgJT4lIAogICAgZmlsdGVyKGJpbnNpemUgPj0gMi41ZTUpICU+JQogICAgZ2dwbG90KC4sIGFlcyh4ID0gc3RhcnQsIHkgPSBub3JtY292LCBmaWxsID0gc2FtcGxlKSkgKwogICAgZ2VvbV9saW5lKGFscGhhID0gMC4yKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IGZpbHRlcihkZiwgY2hyb20gPT0gY2hyICYgc2FtcGxlID09IGRpaGFwICYgYmluc2l6ZSA+PSAyLjVlNSksIGNvbG9yID0gInJlZCIsIHNpemUgPSAxLjIpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCw2ZTcsYnk9MmU3KSwgbGFiZWxzPXNlcSgwLDYwLGJ5PTIwKSkgKwogICAgZmFjZXRfd3JhcCh+Y2hyb20sIHN0cmlwLnBvc2l0aW9uID0gInIiKSArCiAgICBsYWJzKHggPSAiUG9zaXRpb24gKE1iKSIsIHkgPSAiU3RhbmRhcmRpemVkIENvdmVyYWdlIikgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZShzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpLAogICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksCiAgICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKQogIHJldHVybihwbHQpCn0KCmhpY292IDwtIGZ1bmN0aW9uKGRmLCBkaWhhcCwgY2hyLCBzLCBlKSB7CiAgCiAgc2NfdG9fdXNlIDwtIGRpaGFwICU+JSAKICAgIHN0cl9yZW1vdmUoIlsyNF14XyIpICU+JSAKICAgIHN0cl9yZXBsYWNlKC4sICJfIiwgIi4iKQogICMgcHJpbnQoc2NfdG9fdXNlKQogIAogIHNjX2xvYyA8LSBzY1t3aGljaChuYW1lcyhzYykgPT0gc2NfdG9fdXNlKV0KICAKICBwbHQgPC0gZGYgJT4lIAogICAgZmlsdGVyKGNocm9tID09IGNocikgJT4lIAogICAgZmlsdGVyKGJldHdlZW4oc3RhcnQsIHMsIGUpKSAlPiUgCiAgICBmaWx0ZXIoTl9jb250ZW50IDw9IDAuMykgJT4lIAogICAgZmlsdGVyKHNhbXBsZSA9PSBkaWhhcCkgJT4lIAogICAgZ2dwbG90KC4sIGFlcyh4ID0gc3RhcnQsIHkgPSBnY19ub3JtX2RwKSkgKwogICAgIyBnZW9tX3BvaW50KCkgKwogICAgIyBnZW9tX2xpbmUoKSArCiAgICBsYWJzKHggPSAiUG9zaXRpb24gKE1iKSIsIHkgPSBwYXN0ZShzY190b191c2UsICJDb3B5IE51bWJlciIsIHNlcCA9ICIgIikpICsKICAgIGZhY2V0X3dyYXAofmNocm9tLCBzdHJpcC5wb3NpdGlvbiA9ICJyIikgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShzLGUsIGJ5ID0gMi41ZTUpLCBsYWJlbHMgPSBzZXEocy8xZTYsIGUvMWU2LCBieSA9IDAuMjUpKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAyKnNjX2xvYyksIGJyZWFrcyA9IGMoMCwgMC41KnNjX2xvYywgc2NfbG9jLCAxLjUqc2NfbG9jLCAyKnNjX2xvYyksIGxhYmVscyA9IHNlcSgwLDQpKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwKICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkpCiAgcmV0dXJuKHBsdCkKfQpgYGAKCmBgYHtyfQpzNV8xIDwtIG92ZXJsYXlfZW1waGFzaXplX29uZShiaW5fZG9zYWdlLCAiMnhfTE9QODY4XzAwNCIsICJjaHIwNiIpCnM1XzIgPC0gb3ZlcmxheV9lbXBoYXNpemVfb25lKGJpbl9kb3NhZ2UsICIyeF9MT1A4NjhfMDY0IiwgImNocjA2IikKczVfMyA8LSBvdmVybGF5X2VtcGhhc2l6ZV9vbmUoYmluX2Rvc2FnZSwgIjJ4X0xPUDg2OF8zMDUiLCAiY2hyMDYiKQpzNV80IDwtIGhpY292KGRwLCAiMnhfTE9QODY4XzAwNCIsICJjaHIwNiIsIDMuMmU3LCAzLjRlNykgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKQpzNV81IDwtIGhpY292KGRwLCAiMnhfTE9QODY4XzA2NCIsICJjaHIwNiIsIDMuMmU3LCAzLjRlNykgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKQpzNV82IDwtIGhpY292KGRwLCAiMnhfTE9QODY4XzMwNSIsICJjaHIwNiIsIDMuMmU3LCAzLjRlNykgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKQpzNV83IDwtIGhpY292KGRwLCAiMnhfTE9QODY4XzAwNCIsICJjaHIwNiIsIDAsIDZlNykgKyBnZW9tX3BvaW50KGFscGhhID0gMC4zLCBzaXplID0gMC44KSArIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDZlNyksIGJyZWFrcyA9IHNlcSgwLCA2ZTcsIGJ5ID0gMmU3KSwgbGFiZWxzID0gc2VxKDAsIDYwLCBieSA9IDIwKSkKczVfOCA8LSBoaWNvdihkcCwgIjJ4X0xPUDg2OF8wNjQiLCAiY2hyMDYiLCAwLCA2ZTcpICsgZ2VvbV9wb2ludChhbHBoYSA9IDAuMywgc2l6ZSA9IDAuOCkgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA2ZTcpLCBicmVha3MgPSBzZXEoMCwgNmU3LCBieSA9IDJlNyksIGxhYmVscyA9IHNlcSgwLCA2MCwgYnkgPSAyMCkpCnM1XzkgPC0gaGljb3YoZHAsICIyeF9MT1A4NjhfMzA1IiwgImNocjA2IiwgMCwgNmU3KSArIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMsIHNpemUgPSAwLjgpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNmU3KSwgYnJlYWtzID0gc2VxKDAsIDZlNywgYnkgPSAyZTcpLCBsYWJlbHMgPSBzZXEoMCwgNjAsIGJ5ID0gMjApKQpgYGAKCmBgYHtyfQpzNSA8LSBncmlkLmFycmFuZ2UoczVfMSwgczVfMiwgczVfMywgczVfNCwgczVfNSwgczVfNiwgczVfNywgczVfOCwgczVfOSwgbnJvdyA9IDMpCmdnc2F2ZSgiRmlnX1M1LnBuZyIsIHBsb3QgPSBzNSwgd2lkdGggPSAxOCwgaGVpZ2h0ID0gMTIsIHVuaXRzID0gImluIiwgZGV2aWNlID0gInBuZyIpCmBgYAoKRmlnIFM0OiBLZXJuZWwgZGVuc2l0eSBlc3RpbWF0b3IgcGxvdHMgaWxsbHVzdHJhdGluZyBkb3NhZ2UgdmFyaWFudCBjbHVzdGVyaW5nIHRvIGdldCBnZW5vdHlwZXMKTm90ZSwgcmVkIHBvaW50cyB3ZXJlIGRyYXduIGluIGFzIG1hbnVhbCBwb2ludHMsIHVzaW5nIHggdmFsdWVzIHNwZWNpZmllZCBhY2NvcmRpbmcgdG8gdGhlCmNsdXN0ZXIgY2VudGVyLCBhbmQgdGhlIFkgYXhpcyBwb2ludCBkcmF3biBzL3QgaXQgd2FzIGF0IHRoZSBwZWFrIG9mIHRoZSBrZXJuZWwgZGVuc2l0eSBmdW5jdGlvbi4KCmBgYHtyfQprZGVfYmluIDwtIGZ1bmN0aW9uKGRmLCBjaHIsIHMpIHsKICBhY3RpdmVfYmluIDwtIGZpbHRlcihkZiwgY2hyb20gPT0gY2hyICYgc3RhcnQgPT0gcykgJT4lIAogICAgbXV0YXRlKGJpbiA9IHBhc3RlKGNocm9tLCBzdGFydCwgZW5kLCBzZXAgPSAiXyIpKSAKICBwbHQgPC0gZ2dwbG90KGFjdGl2ZV9iaW4sIGFlcyh4ID0gbm9ybWNvdikpICsKICAgIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBiaW53aWR0aCA9IDAuMSwgZmlsbCA9ICJibHVlIiwgYWxwaGEgPSAwLjUpICsKICAgIGdlb21fZGVuc2l0eShrZXJuZWwgPSAiZXAiLCBidyA9IHF1YW50aWxlKGRpc3QoYWN0aXZlX2JpbiRub3JtY292KSwgMC40KSkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCw0KSkgKwogICAgZmFjZXRfd3JhcCh+YmluLCBzdHJpcC5wb3NpdGlvbiA9ICJyIikKICByZXR1cm4ocGx0KQp9CmBgYAoKYGBge3J9CnM0XzEgPC0ga2RlX2JpbihiaW5fZG9zYWdlLCAiY2hyMDEiLCA0LjI1ZTYpCnM0XzIgPC0ga2RlX2JpbihiaW5fZG9zYWdlLCAiY2hyMDEiLCAyLjQyNWU3KQpzNF8zIDwtIGtkZV9iaW4oYmluX2Rvc2FnZSwgImNocjAxIiwgNy45NWU3KQpnZ3NhdmUoIkZpZ19TNF8xLnBuZyIsIHBsb3QgPSBzNF8xLCB3aWR0aCA9IDQsIGhlaWdodCA9IDIsIHVuaXRzID0gImluIiwgZGV2aWNlID0gInBuZyIpCmdnc2F2ZSgiRmlnX1M0XzIucG5nIiwgcGxvdCA9IHM0XzIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMiwgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSAicG5nIikKZ2dzYXZlKCJGaWdfUzRfMy5wbmciLCBwbG90ID0gczRfMywgd2lkdGggPSA0LCBoZWlnaHQgPSAyLCB1bml0cyA9ICJpbiIsIGRldmljZSA9ICJwbmciKQpgYGAKCkZpZy4gUzY6IFBvd2VyIGFuYWx5c2lzIG9mIHJhcmUgaW5kZWxzIGluIExPUCBkaWhhcGxvaWQgcG9wdWxhdGlvbi4KTm90ZSwgSSBhZGRlZCB0aGUgZmlndXJlIGxlZ2VuZCBpbiBBZmZpbml0eSBEZXNpZ25lciBieSBjb3B5aW5nIHRoZQpsZWdlbmQgZnJvbSBmaWd1cmUgczZfbGVnZW5kCgpgYGB7cn0Kc2ltaHliX2xlc19hbGxlbGVzIDwtIHJlYWRfdHN2KCIuLi9leHBlcmltZW50cy8zX2Zha2VfaHlicmlkcy9pbmRlbF9iaW5fYWxsZWxlc19zaW1oeWIudHh0IiwgY29sX25hbWVzID0gVCkgJT4lIAogIG11dGF0ZShjb250cm9sX2dyb3VwID0gaWZlbHNlKGdyZXBsKCJTUlI2MTIzMDMxIiwgc2FtcGxlKSwgIlNpbXVsYXRlZCBBbGNhIFRhcm1hIHggUEw0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZ3JlcGwoIlNSUjYxMjMxODMiLCBzYW1wbGUpLCAiU2ltdWxhdGVkIEFsY2EgVGFybWEgeCBJVlAxMDEiLCAiU2ltdWxhdGVkIE1hdHJpbGluZWFsIikpKSAlPiUgCiAgbXV0YXRlKGNvbnRyb2xfZ3JvdXAgPSBmYWN0b3IoY29udHJvbF9ncm91cCwgbGV2ZWxzID0gYygiU2ltdWxhdGVkIE1hdHJpbGluZWFsIiwgIlNpbXVsYXRlZCBBbGNhIFRhcm1hIHggSVZQMTAxIiwgIlNpbXVsYXRlZCBBbGNhIFRhcm1hIHggUEw0IikpKSAlPiUgCiAgbXV0YXRlKGJpbiA9IHBhc3RlKGNocm9tLCBhcy5pbnRlZ2VyKHN0YXJ0KSwgYXMuaW50ZWdlcihlbmQpLCBzZXAgPSAiXyIpKQpgYGAKCmBgYHtyfQpoZWFkKHNpbWh5Yl9sZXNfYWxsZWxlcykKYGBgCgpgYGB7cn0KcGxvdF9wb3dlcl9zaW1oeWJfbGVzaW9uIDwtIGZ1bmN0aW9uKGRmLCBjaHIsIHMpIHsKICBwbHQgPC0gZGYgJT4lIAogICAgZmlsdGVyKGNocm9tID09IGNocikgJT4lIAogICAgZmlsdGVyKHN0YXJ0ID09IHMpICU+JSAKICAgIGdncGxvdCguLCBhZXMoeCA9IFBlcmNBTGVzaW9uLCBmaWxsID0gY29udHJvbF9ncm91cCkpICsKICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMSwgYWxwaGEgPSAwLjgpICsKICAgIGxhYnMoeCA9ICJQZXJjZW50IEhJIEFsbGVsZSIsIHkgPSAiQ291bnQiKSArCiAgICBmYWNldF93cmFwKH5iaW4pICsKICAgIHRoZW1lX2J3KCkgKwogICAgIyBndWlkZXMoZmlsbCA9IEYpICsKICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0wLjAxLDEpKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDBCQTM4IiwgIiNGODc2NkQiLCAiIzAwQkZDNCIpKSArCiAgICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksCiAgICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpKQogIHJldHVybihwbHQpCn0KYGBgCgpgYGB7cn0KczZfMSA8LSBwbG90X3Bvd2VyX3NpbWh5Yl9sZXNpb24oc2ltaHliX2xlc19hbGxlbGVzLCAiY2hyMDEiLCAyLjAyNWU3KSArCiAgZ3VpZGVzKGZpbGwgPSBGKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMC4xNSwgeT00MCwgbGFiZWwgPSAiTE9QODY4LjM5OCIpICsKICBhbm5vdGF0ZSgic2VnbWVudCIsIHggPSAwLCB4ZW5kID0gMC4xNSwgeSA9IDAsIHllbmQgPSAzOCwgbGluZXR5cGUgPSAiZGFzaGVkIikKCnM2XzIgPC0gcGxvdF9wb3dlcl9zaW1oeWJfbGVzaW9uKHNpbWh5Yl9sZXNfYWxsZWxlcywgImNocjAxIiwgMi4zMjVlNykgKwogIGd1aWRlcyhmaWxsID0gRikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDAuMTUsIHk9NDAsIGxhYmVsID0gIkxPUDg2OC4zOTgiKSArCiAgYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0gMCwgeGVuZCA9IDAuMTUsIHkgPSAwLCB5ZW5kID0gMzgsIGxpbmV0eXBlID0gImRhc2hlZCIpCgpzNl8zIDwtcGxvdF9wb3dlcl9zaW1oeWJfbGVzaW9uKHNpbWh5Yl9sZXNfYWxsZWxlcywgImNocjAxIiwgMi40MjVlNykgKwogIGd1aWRlcyhmaWxsID0gRikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDAuMTUsIHk9NDAsIGxhYmVsID0gIkxPUDg2OC40ODgiKSArCiAgYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0gMC4wMDk0MzM5NjIyNjQxNTA5NDMsIHhlbmQgPSAwLjE1LCB5ID0gMCwgeWVuZCA9IDM4LCBsaW5ldHlwZSA9ICJkYXNoZWQiKQoKczZfNCA8LXBsb3RfcG93ZXJfc2ltaHliX2xlc2lvbihzaW1oeWJfbGVzX2FsbGVsZXMsICJjaHIwMSIsIDUuMjc1ZTcpICsKICBndWlkZXMoZmlsbCA9IEYpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAwLjE1LCB5PTQwLCBsYWJlbCA9ICJMT1A4NjguMzk4IikgKwogIGFubm90YXRlKCJzZWdtZW50IiwgeCA9IDAsIHhlbmQgPSAwLjE1LCB5ID0gMCwgeWVuZCA9IDM4LCBsaW5ldHlwZSA9ICJkYXNoZWQiKQoKczZfNSA8LSBwbG90X3Bvd2VyX3NpbWh5Yl9sZXNpb24oc2ltaHliX2xlc19hbGxlbGVzLCAiY2hyMDEiLCA1LjRlNykgKwogIGd1aWRlcyhmaWxsID0gRikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDAuMTUsIHk9NDAsIGxhYmVsID0gIkxPUDg2OC4zOTgiKSArCiAgYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0gMCwgeGVuZCA9IDAuMTUsIHkgPSAwLCB5ZW5kID0gMzgsIGxpbmV0eXBlID0gImRhc2hlZCIpCgpzNl82IDwtIHBsb3RfcG93ZXJfc2ltaHliX2xlc2lvbihzaW1oeWJfbGVzX2FsbGVsZXMsICJjaHIwMSIsIDYuN2U3KSArCiAgZ3VpZGVzKGZpbGwgPSBGKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMC4yNiwgeT0zNSwgbGFiZWwgPSAiTE9QODY4LjI5MiIpICsKICBhbm5vdGF0ZSgic2VnbWVudCIsIHggPSAwLjAxMDQxNjY2NywgeGVuZCA9IDAuMjYsIHkgPSAwLCB5ZW5kID0gMzMsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAwLjE1LCB5PTQ1LCBsYWJlbCA9ICJMT1A4NjguNDYwIikgKwogIGFubm90YXRlKCJzZWdtZW50IiwgeCA9IDAuMDAzNzAzNzA0LCB4ZW5kID0gMC4xNSwgeSA9IDAsIHllbmQgPSA0MywgbGluZXR5cGUgPSAiZGFzaGVkIikKCnM2XzcgPC0gcGxvdF9wb3dlcl9zaW1oeWJfbGVzaW9uKHNpbWh5Yl9sZXNfYWxsZWxlcywgImNocjA0IiwgMS4zZTcpICsKICBndWlkZXMoZmlsbCA9IEYpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAwLjE1LCB5PTU1LCBsYWJlbCA9ICJMT1A4NjguMjcyIikgKwogIGFubm90YXRlKCJzZWdtZW50IiwgeCA9IDAuMDAyMDc0Njg4Nzk2NjgwNDk4LCB4ZW5kID0gMC4xNSwgeSA9IDAsIHllbmQgPSA1MywgbGluZXR5cGUgPSAiZGFzaGVkIikKCnM2XzggPC0gcGxvdF9wb3dlcl9zaW1oeWJfbGVzaW9uKHNpbWh5Yl9sZXNfYWxsZWxlcywgImNocjA5IiwgMy4yNzVlNykgKwogIGd1aWRlcyhmaWxsID0gRikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDAuMTUsIHk9NDAsIGxhYmVsID0gIkxPUDg2OC40OTMiKSArCiAgYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0gMCwgeGVuZCA9IDAuMTUsIHkgPSAwLCB5ZW5kID0gMzgsIGxpbmV0eXBlID0gImRhc2hlZCIpCgpzNl85IDwtIHBsb3RfcG93ZXJfc2ltaHliX2xlc2lvbihzaW1oeWJfbGVzX2FsbGVsZXMsICJjaHIwOSIsIDRlNykgKwogIGd1aWRlcyhmaWxsID0gRikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDAuMTUsIHk9NDAsIGxhYmVsID0gIkxPUDg2OC40OTMiKSArCiAgYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0gMCwgeGVuZCA9IDAuMTUsIHkgPSAwLCB5ZW5kID0gMzgsIGxpbmV0eXBlID0gImRhc2hlZCIpCgpzNiA8LSBncmlkLmFycmFuZ2UoczZfMSwgczZfMiwgczZfMywgczZfNCwgczZfNSwgczZfNiwgczZfNywgczZfOCwgczZfOSwgbnJvdyA9IDMpCmdnc2F2ZSgiRmlnUzYucGRmIiwgd2lkdGggPSAxNiwgaGVpZ2h0ID0gMTAsIHVuaXRzID0gImluIiwgZGV2aWNlID0gInBkZiIsIHBsb3QgPSBzNikKCnM2X2xlZ2VuZCA8LSBwbG90X3Bvd2VyX3NpbWh5Yl9sZXNpb24oc2ltaHliX2xlc19hbGxlbGVzLCAiY2hyMDkiLCA0ZTcpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKQpnZ3NhdmUoIkZpZ1M2X2xlZ2VuZC5wZGYiLCBwbG90ID0gczZfbGVnZW5kLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSAzLCB1bml0cyA9ICJpbiIsIGRldmljZSA9ICJwZGYiKQpgYGAKCkZpZy4gUzI6IEJpbm5lZCBTTlAgcmVzdWx0LCBpbmNsdWRpbmcgc2ltdWxhdGVkIGh5YnJpZCBwb3dlciB0ZXN0LgoKYGBge3J9Cm1lbHRfYmluX2FsbGVsZXMgPC0gZnVuY3Rpb24oeCkgewogIGRmIDwtIHJlYWRfdHN2KHgsIG5hID0gIi4iKQogIAogIE9ic0hJIDwtIGRmICU+JSAKICAgIHNlbGVjdChDaHJvbSxTdGFydCxFbmQsTWF4LG1hdGNoZXMoIk9icyVBJCIpKSAlPiUgCiAgICBtdXRhdGUoY2hyYmluID0gZmxvb3IoU3RhcnQvZGYkRW5kWzFdKSkgJT4lIAogICAgZ2F0aGVyKEluZCwgT2JzUGVySEksIC1DaHJvbSwgLVN0YXJ0LCAtRW5kLCAtTWF4LCAtY2hyYmluKSAlPiUgCiAgICBtdXRhdGUoSW5kID0gc3RyX3JlcGxhY2VfYWxsKEluZCwgInYtKC4rKS1PYnMlQSIsICJcXDEiKSkKICAKICBDYWxjSEkgPC0gZGYgJT4lIAogICAgc2VsZWN0KENocm9tLCBTdGFydCwgRW5kLCBNYXgsIG1hdGNoZXMoJ0NhbGMlQSQnKSkgJT4lIAogICAgbXV0YXRlKGNocmJpbiA9IGZsb29yKFN0YXJ0L2RmJEVuZFsxXSkpICU+JSAKICAgIGdhdGhlcihJbmQsIENhbGNQZXJISSwgLUNocm9tLCAtU3RhcnQsIC1FbmQsIC1NYXgsIC1jaHJiaW4pICU+JSAKICAgIG11dGF0ZShJbmQgPSBzdHJfcmVwbGFjZV9hbGwoSW5kLCAidi0oLispLUNhbGMlQSIsICJcXDEiKSkgCiAgCiAgQ292IDwtIGRmICU+JSAKICAgIHNlbGVjdChDaHJvbSwgU3RhcnQsIEVuZCwgTWF4LCBtYXRjaGVzKCdDb3YkJykpICU+JSAKICAgIG11dGF0ZShjaHJiaW4gPSBmbG9vcihTdGFydC9kZiRFbmRbMV0pKSAlPiUgCiAgICBnYXRoZXIoSW5kLCBDb3YsIC1DaHJvbSwgLVN0YXJ0LCAtRW5kLCAtTWF4LCAtY2hyYmluKSAlPiUgCiAgICBtdXRhdGUoSW5kID0gc3RyX3JlcGxhY2VfYWxsKEluZCwgInYtKC4rKS1Db3YiLCAiXFwxIikpCiAgCiAgZGYyIDwtIE9ic0hJICU+JSAKICAgIGlubmVyX2pvaW4oLixDb3YpICU+JSAKICAgIG11dGF0ZShISWNhbGxzID0gcm91bmQoQ292ICogT2JzUGVySEkgLyAxMDApKSAlPiUgCiAgICBmaWx0ZXIoQ2hyb20gIT0gImNocjAwIikgJT4lIAogICAgIyBmaWx0ZXIoIWdyZXBsKCJzdWIiLCBJbmQpKSAlPiUgCiAgICBtdXRhdGUocHJlbmR1Y2VyID0gc3RyX2V4dHJhY3QoSW5kLCAiKFNSUjYxMjMwMzEpfChTUlI2MTIzMTgzKSIpKSAlPiUgCiAgICBtdXRhdGUoSW5kdWNlciA9IGlmZWxzZShwcmVuZHVjZXIgPT0gIlNSUjYxMjMwMzEiLCAiUEw0IiwgTkEpKSAlPiUgCiAgICBtdXRhdGUoSW5kdWNlciA9IGlmZWxzZShwcmVuZHVjZXIgPT0gIlNSUjYxMjMxODMiLCAiSVZQMTAxIiwgSW5kdWNlcikpICU+JSAKICAgIG11dGF0ZShPYnNQZXJISV9maWx0ID0gaWZlbHNlKENvdiA+PSAxMCwgT2JzUGVySEksIE5BKSkgJT4lIAogICAgbXV0YXRlKHN0YXJ0X2NlbiA9IFN0YXJ0ICsgKEVuZC1TdGFydCkvMikgCiAgcHJpbnQoaGVhZChkZjIpKQogIAogIHJldHVybihkZjIpCn0KYGBgCgpgYGB7cn0KYmlnIDwtIG1lbHRfYmluX2FsbGVsZXMoIi4uL2V4cGVyaW1lbnRzLzNfZmFrZV9oeWJyaWRzLzFNYl9iaW5fYWxsZWxlc19zaW1oeWIudHh0IikgJT4lIAogIG11dGF0ZShgQ29udHJvbCBHcm91cGAgPSBpZmVsc2UoSW5kdWNlciA9PSAiUEw0IiwgIlNpbXVsYXRlZCBBbGNhIFRhcm1hIHggUEw0IiwgaWZlbHNlKEluZHVjZXIgPT0gIklWUDEwMSIsICJTaW11bGF0ZWQgQWxjYSBUYXJtYSB4IElWUDEwMSIsICJTaW11bGF0ZWQgTWF0cmlsaW5lYWwiKSkpCmBgYAoKYGBge3J9CnBjIDwtIGJpZyAlPiUgCiAgZmlsdGVyKGdyZXBsKCJTUlI2MTIzMDMxfFNSUjYxMjMxODMiLCBJbmQpKQoKbmMgPC0gYmlnICU+JSAKICBmaWx0ZXIoZ3JlcGwoInVuaXBhcmVudGFsIiwgSW5kKSkKYGBgCgpgYGB7cn0KIyBEZWZpbmUgYmlucwpiaWdwIDwtIGJpZyAlPiUgCiAgc2VsZWN0KENocm9tLCBTdGFydCwgRW5kKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgbXV0YXRlKG92ZXJsYXBfdGVzdCA9IE5BKSAlPiUgCiAgbXV0YXRlKG1pc3Npbmdfbl90ZXN0ID0gTkEpICU+JQogIG11dGF0ZShtaXNzaW5nX25fZnJhYyA9IE5BKSAlPiUgCiAgbXV0YXRlKG1pc3NpbmdfcF90ZXN0ID0gTkEpICU+JSAKICBtdXRhdGUobWlzc2luZ19wX2ZyYWMgPSBOQSkKbnJvdyhiaWdwKQoKIyBkZWZpbmUgY3JpdGljYWwgZnJhY3Rpb24gb2YgbWlzc2luZyBkYXRhCm5hZnJhY19jcml0IDwtIDAuMDUgIyBtYXkgaGF2ZSB0byBmdXR6IHdpdGggdGhpcwpgYGAKCmBgYHtyfQpmb3IgKGkgaW4gMTpucm93KGJpZ3ApKSB7CiAgCiAgY2hyb20gPC0gYmlncCRDaHJvbVtpXQogIHN0cnQgPC0gYmlncCRTdGFydFtpXQogIGVuZGQgPC0gYmlncCRFbmRbaV0KICAKICAjIERlZmluZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGJpbiBpbiBuZWdhdGl2ZSBjb250cm9sIHBvcHVsYXRpb24KICBybmdfcCA8LSBwYyAlPiUgCiAgICBmaWx0ZXIoQ2hyb20gPT0gY2hyb20pICU+JSAKICAgIGZpbHRlcihTdGFydCA9PSBzdHJ0KSAlPiUgCiAgICBmaWx0ZXIoRW5kID09IGVuZGQpICU+JSAKICAgIHNlbGVjdChPYnNQZXJISSkKICAKICBwbWluIDwtIG1pbihybmdfcCRPYnNQZXJISSwgbmEucm0gPSBUKQogIHByaW50KHBhc3RlKCJwbWluOiIsIHBtaW4pKQogIAogIHBtYXggPC0gbWF4KHJuZ19wJE9ic1BlckhJLCBuYS5ybSA9IFQpCiAgcHJpbnQocGFzdGUoInBtYXg6IiwgcG1heCkpCiAgCiAgbmFmcmFjX3AgPC0gc3VtKGlzLm5hKHJuZ19wJE9ic1BlckhJKSkgLyBsZW5ndGgocm5nX3AkT2JzUGVySEkpCiAgCiAgIyBEZWZpbmUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBiaW4gaW4gcG9zaXRpdmUgY29udHJvbCBwb3B1bGF0aW9uCiAgcm5nX24gPC0gbmMgJT4lIAogICAgZmlsdGVyKENocm9tID09IGNocm9tKSAlPiUgCiAgICBmaWx0ZXIoU3RhcnQgPT0gc3RydCkgJT4lIAogICAgZmlsdGVyKEVuZCA9PSBlbmRkKSAlPiUgCiAgICBzZWxlY3QoT2JzUGVySEkpCiAgCiAgbm1pbiA8LSBtaW4ocm5nX24kT2JzUGVySEksIG5hLnJtID0gVCkKICBwcmludChwYXN0ZSgibm1pbjoiLCBubWluKSkKICAKICBubWF4IDwtIG1heChybmdfbiRPYnNQZXJISSwgbmEucm0gPSBUKQogIHByaW50KHBhc3RlKCJubWF4OiIsIG5tYXgpKQogIAogIG5hZnJhY19uIDwtIHN1bShpcy5uYShybmdfbiRPYnNQZXJISSkpIC8gbGVuZ3RoKHJuZ19uJE9ic1BlckhJKQogIAogICMgRGVmaW5lIFBBU1MvRkFJTCBjcml0ZXJpYSBhcyB2YXJpYWJsZXMgaW4gb3JpZ2luYWwgZGF0YSBmcmFtZQogICMgZmlyc3QgZmFpbHVyZSBjcml0ZXJpb246IGlmIG1heCBvZiBuZWdhdGl2ZSBjb250cm9sIGdyZWF0ZXIgdGhhbiBtaW4gb2YgcG9zaXRpdmUgY29udHJvbAogIGJpZ3Akb3ZlcmxhcF90ZXN0W2ldID0gaWZlbHNlKG5tYXggPj0gcG1pbiwgIkZBSUwiLCAiUEFTUyIpICMgY2FuIHRoZW4gY2JpbmQgd2hlbiBJJ20gZG9uZS4KICAKICAjIHNlY29uZCBmYWlsdHVyZSBjcml0ZXJpb246IG1pc3NpbmcgZGF0YSBpbiBuZWdhdGl2ZSBjb250cm9sCiAgYmlncCRtaXNzaW5nX25fdGVzdFtpXSA8LSBpZmVsc2UobmFmcmFjX24gPj0gbmFmcmFjX2NyaXQsICJGQUlMIiwgIlBBU1MiKQogIGJpZ3AkbWlzc2luZ19uX2ZyYWNbaV0gPC0gbmFmcmFjX24KICAKICAjIHRoaXJkIGZhaWx1cmUgY3JpdGVyaW9uOiBtaXNzaW5nIGRhdGEgaW4gcG9zaXRpdmUgY29udHJvbAogIGJpZ3AkbWlzc2luZ19wX3Rlc3RbaV0gPC0gaWZlbHNlKG5hZnJhY19wID49IG5hZnJhY19jcml0LCAiRkFJTCIsICJQQVNTIikKICBiaWdwJG1pc3NpbmdfcF9mcmFjW2ldIDwtIG5hZnJhY19wCn0KYGBgCgpgYGB7cn0KcWNfYmlucyA8LSBsZWZ0X2pvaW4ocGMsIGJpZ3ApICU+JSAKICBtdXRhdGUoT2JzUGVySElfcWMgPSBpZmVsc2Uob3ZlcmxhcF90ZXN0ID09ICJQQVNTIiwgT2JzUGVySEksIE5BKSkKYGBgCgpgYGB7cn0KcmVhbCA8LSBtZWx0X2Jpbl9hbGxlbGVzKCIuLi9leHBlcmltZW50cy80X2xvd19jb3Zfc25wLzFNYl9iaW5fYWxsZWxlc19MT1AudHh0IikKYGBgCgpgYGB7cn0KcmVhbDMgPC0gcmVhbCAlPiUgCiAgZmlsdGVyKCEoSW5kICVpbiUgYygiMnhfSVZQXzEwMSIsICIyeF9QTF80IiwgIjR4X0xPUDg2OCIsICIyeF9MT1A4NjhfMjc5IikpKSAlPiUgCiAgZmlsdGVyKENocm9tICE9ICJjaHIwMCIpICU+JSAKICBsZWZ0X2pvaW4oLiwgYmlncCkgJT4lIAogIG11dGF0ZShPYnNQZXJISV9xYyA9IGlmZWxzZShvdmVybGFwX3Rlc3QgPT0gIlBBU1MiLCBPYnNQZXJISSwgTkEpKSAlPiUgCiAgbXV0YXRlKE9ic1BlckhJX3FjX2NvdiA9IGlmZWxzZShDb3YgPCAzMCwgTkEsIE9ic1BlckhJX3FjKSkgJT4lIAogIG11dGF0ZShPYnNQZXJISV9xY181MGNvdiA9IGlmZWxzZShDb3YgPCA1MCwgTkEsIE9ic1BlckhJX3FjKSkKYGBgCgpgYGB7cn0KZmlnX3MyIDwtIHJlYWwzICU+JSAKICBnZ3Bsb3QoLiwgYWVzKHggPSBTdGFydCwgeSA9IE9ic1BlckhJX3FjX2NvdiwgZmlsbCA9IEluZCkpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjUpICsKICBnZW9tX2xpbmUoZGF0YSA9IHFjX2JpbnMsIGFlcyh4ID0gU3RhcnQsIHkgPSBPYnNQZXJISV9xYywgZmlsbCA9IEluZCwgY29sb3IgPSBgQ29udHJvbCBHcm91cGApLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuMykgKwogIGZhY2V0X3dyYXAofkNocm9tLCBucm93ID0gNiwgc3RyaXAucG9zaXRpb24gPSAiciIpICsKICBsYWJzKHggPSAiUG9zaXRpb24gKE1iKSIsIHkgPSAiJUhJIFNOUHMiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCw4ZTcpLCBicmVha3MgPSBzZXEoMCw4ZTcsYnk9MmU3KSwgbGFiZWxzPXNlcSgwLDgwLGJ5PTIwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsMTAwKSkgKwogICMgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwMEJBMzgiLCAiIzYxOUNGRiIsICIjRjg3NjZEIikpICsKICB0aGVtZV9idygpICsKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiZG90dGVkIiksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkKZmlnX3MyCmdnc2F2ZSgiRmlnX1MyLnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDEwLCB1bml0cyA9ICJpbiIsIGRldmljZSA9ICJwbmciLCBwbG90ID0gZmlnX3MyKQpnZ3NhdmUoIkZpZ19TMi5wZGYiLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSAxMCwgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSAicGRmIiwgcGxvdCA9IGZpZ19zMikKYGBgCgpPdmVybGF5IGNvbWJpbmVkIGRvc2FnZSBhbmQgMU1iIFNOUCBwbG90cyBmb3IgRmlnLiBTMS4KVGhlc2Ugd2VyZSBsYXRlciBwdXQgdG9nZXRoZXIgaW4gQWZmaW5pdHkgRGVzaWduZXIgd2l0aCBtZXRhcGhhc2Ugc3ByZWFkcywgaWYgc3ByZWFkcyB3ZXJlIGF2YWlsYWJsZS4KVE9ETzogcHV0IHJhdyBpbWFnZXMgb2Ygc3ByZWFkcyBpbiBhIHNlcGFyYXRlIGZvbGRlci4KCmBgYHtyfQpudW1ibGFua3Nfc25wIDwtIDEwCm1pZCA8LSBmdW5jdGlvbih4KSB7CiAgbiA9IGZsb29yKG5yb3coeCkvMikKICByZXR1cm4oeCRiaW5bbl0pCn0KYGBgCgpgYGB7cn0KcGxvdC5zbnAgPC0gZnVuY3Rpb24oeCx5LHopIHsKICBrZWVwIDwtIHJlYWwzICU+JSAKICAgIGZpbHRlcihJbmQgPT0geCkgJT4lIAogICAgc2VsZWN0KENocm9tLCBTdGFydCwgRW5kLCBNYXgsIGNocmJpbiwgSW5kLCBPYnNQZXJISSwgQ292LCBISWNhbGxzLCBPYnNQZXJISV9xY19jb3YpCiAgICAKICBrZWVwJGJpbiA8LSBzZXEoMTpucm93KGtlZXApKQogICMgcHJpbnQoaGVhZChrZWVwKSkKICAKICBzdHVmIDwtIGMocmVwKE5BLCBudW1ibGFua3Nfc25wKSkKICBzdHVmZmVyIDwtIGRhdGEuZnJhbWUoIkNocm9tIj1zdHVmLAogICAgICAgICAgICAgICAgICAgICAgICAiU3RhcnQiPXN0dWYsCiAgICAgICAgICAgICAgICAgICAgICAgICJFbmQiPXN0dWYsCiAgICAgICAgICAgICAgICAgICAgICAgICJNYXgiPXN0dWYsCiAgICAgICAgICAgICAgICAgICAgICAgICJjaHJiaW4iPXN0dWYsCiAgICAgICAgICAgICAgICAgICAgICAgICJJbmQiPXN0dWYsCiAgICAgICAgICAgICAgICAgICAgICAgICJPYnNQZXJISSI9c3R1ZiwKICAgICAgICAgICAgICAgICAgICAgICAgIkNvdiI9c3R1ZiwKICAgICAgICAgICAgICAgICAgICAgICAgIkhJY2FsbHMiPXN0dWYsCiAgICAgICAgICAgICAgICAgICAgICAgICJPYnNQZXJISV9xY19jb3YiPXN0dWYsCiAgICAgICAgICAgICAgICAgICAgICAgICJiaW4iPXN0dWYpCiAgY2hyLmxpc3QgPC0gc3BsaXQoa2VlcCwgZj1rZWVwJENocm9tKQogIGNoci5saXN0LnN0dWZmZWQgPC0gbGFwcGx5KGNoci5saXN0WzE6MTFdLCBmdW5jdGlvbih4KSByYmluZCh4LHN0dWZmZXIpKQogIGluZC5tb2QgPC0gYmluZF9yb3dzKGNoci5saXN0LnN0dWZmZWQsIGNoci5saXN0W1sxMl1dKQogIGluZC5tb2QkYmluMiA8LSBzZXEoMTpucm93KGluZC5tb2QpKQogIAogIG1pZHBvaW50cyA8LSBzYXBwbHkoY2hyLmxpc3RbMToxMl0sIG1pZCkKICBpZiAoeiA9PSBUKSB7CiAgICB4LmF4aXMuYnJlYWtzIDwtIHdoaWNoKGluZC5tb2QkYmluICVpbiUgbWlkcG9pbnRzKQogICAgeC5heGlzLmxhYmVscyA8LSBuYW1lcyhtaWRwb2ludHMpCiAgfSBlbHNlIHsKICAgIHguYXhpcy5icmVha3MgPC0gc2VxKDEsMTIpCiAgICB4LmF4aXMubGFiZWxzIDwtIHJlcCgiIiwxMikKICB9CgogICAgcGx0LmluZC5KTVBsaWtlIDwtIGdncGxvdChpbmQubW9kLCBhZXMoeD1iaW4yLHk9T2JzUGVySElfcWNfY292KSkgKwogICAgbGFicyh4PSIiLCB5PSIlIEhJIFNOUHMiKSArCiAgICBnZ3RpdGxlKCIgIikgKwogICAgIyBnZW9tX2xpbmUoeT0wLjAsIGNvbG9yPSJibGFjayIsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplID0gMikgKwogICAgIyBnZW9tX2xpbmUoeSA9IDMzLzQsIGNvbG9yID0gImJsYWNrIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogICAgZ2VvbV9saW5lKGNvbG9yPXksIGZpbGw9TlVMTCxzaXplPTMpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyhyZXAoeSwxMikpKSArCiAgICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG9yPSJibGFjayIsIGxpbmV0eXBlPSJkYXNoZWQiKSwKICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiLGNvbG9yPSJibGFjayIpLAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xOCwgY29sb3I9ImJsYWNrIiksCiAgICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xOCxjb2xvcj0iYmxhY2siKSwKICAgICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoc2l6ZT0xOCwgYW5nbGU9OTAsIHZqdXN0ID0gMC41LCBtYXJnaW4gPSBtYXJnaW4odCA9IDAsIHIgPSAyNSwgYiA9IDAsIGwgPSAwKSksCiAgICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0yNCxmYWNlPSJib2xkIixoanVzdD0wKSwKICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgc2l6ZSA9IDIpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAyLjAsY29sb3I9ImJsYWNrIikgKwogICAgZ3VpZGVzKGZpbGw9RkFMU0UsIGNvbG9yPUZBTFNFKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoLTUsMTAwKSwgYnJlYWtzPWMoMTAwLDY2LDMzLDApKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXguYXhpcy5icmVha3MsIGxhYmVscz14LmF4aXMubGFiZWxzKQogIHBsdC5pbmQuSk1QbGlrZQp9CmBgYAoKYGBge3J9CiMgcmV0cmlldmVzIG1pZHBvaW50cyBvZiBlYWNoIGNocm9tb3NvbWUKbWlkLmRvc2FnZSA8LSBmdW5jdGlvbih4KSB7CiAgbj1mbG9vcihucm93KHgpLzIpCiAgcmV0dXJuKHgkYmluW25dKQp9CiMgRG9zYWdlIHBsb3QgZnVuY3Rpb24gYXJndW1lbnRzOgojIHggaXMgdGhlIG5hbWUgb2YgdGhlIC50c3YgZmxlIHRvIGJlIHJlYWQgaW4KIyB5IGlzIHRoZSB0aXRsZSBvZiB0aGUgcGxvdC4gSSBnc3ViIHRoZSBzdHJpbmcgeCB0byBnZXQgdGhlIHRpdGxlLiBJIGNvdWxkIGhhcmQgY29kZSB0aGlzIGJ1dCBJIGxlYXZlIGl0IGFzIGFuIGFyZyB0byBiZSBtb3JlIGN1c3RvbWl6YWJsZS4KcGxvdC5kb3NhZ2UgPC0gZnVuY3Rpb24oaW5kLCB5KSB7CiAgdG9kbyA8LSB3aGljaChuYW1lcyhhbGxfZG9zYWdlKSA9PSBpbmQpCiAgIyBwcmludCh0b2RvKQogIAogIHBsdC5kb3NhZ2UgPC0gYWxsX2Rvc2FnZVtbdG9kb11dICU+JQogICAgZ2dwbG90KC4sIGFlcyh4ID0gYmluMiwgeSA9IG5vcm1jb3YpKSArCiAgICBsYWJzKHggPSAiIiwgeT0iU3RhbmRhcmRpemVkXG5Db3B5IE51bWJlciIpICsKICAgIGdlb21fbGluZShjb2xvciA9ICIjMDA4MDgwIiwgZmlsbCA9ICJ3aGl0ZSIsIHNpemUgPSAzKSArCiAgICBnZ3RpdGxlKHkpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDIsIGNvbG9yID0gImJsYWNrIikgKwogICAgZ3VpZGVzKGZpbGwgPSBGLCBjb2xvciA9IEYpICsKICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNSksIGJyZWFrcyA9IHNlcSgwLDUpLCBsYWJlbHMgPSBzZXEoMCw1KSkgKwogICAgdGhlbWUocGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGFuZWwuZ3JpZC5taW5vci55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShjb2xvcj0iYmxhY2siLCBsaW5ldHlwZT0iZGFzaGVkIiksCiAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9IndoaXRlIixjb2xvcj0iYmxhY2siKSwKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTgsY29sb3I9ImJsYWNrIiksCiAgICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KHNpemU9MTgsIGFuZ2xlPTkwLCB2anVzdCA9IDAuNSwgbWFyZ2luID0gbWFyZ2luKHQgPSAwLCByID0gMjUsIGIgPSAwLCBsID0gMCkpLAogICAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MjQsZmFjZT0iYm9sZCIsaGp1c3Q9MCksCiAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyKSkKICBwbHQuZG9zYWdlCn0KYGBgCgpgYGB7cn0KcGxvdC5kb3NhZ2UoIjJ4X0xPUDg2OF8wNjQiLCAiTE9QODY4LjA2NCIpCnBsb3Quc25wKCIyeF9MT1A4NjhfMDA0IiwgIiMwMDgwODAiLCBUUlVFKQpgYGAKCmBgYHtyfQpzdGFjay5wbG90IDwtIGZ1bmN0aW9uKHgpIHsKICBndCA8LSBnZ3Bsb3RHcm9iKHBsb3QuZG9zYWdlKHgsICIiKSkKICBnYiA8LSBnZ3Bsb3RHcm9iKHBsb3Quc25wKHgsICIjMDA4MDgwIiwgVFJVRSkpCiAgZmlnLnMxLnRlbXBsYXRlIDwtIHJiaW5kKGd0LGdiLCBzaXplID0gImZpcnN0IikKICBmaWcuczEudGVtcGxhdGUkd2lkdGhzIDwtIHVuaXQucG1heChndCR3aWR0aHMpCiAgZmlnLnMxLnRlbXBsYXRlJGxheW91dFtncmVwbCgiZ3VpZGUiLCBmaWcuczEudGVtcGxhdGUkbGF5b3V0JG5hbWUpLCBjKCJ0IiwgImIiKV0gPC0gYygxLCBucm93KGZpZy5zMS50ZW1wbGF0ZSkpCiAgZ3JpZC5uZXdwYWdlKCkKICBncmlkLmRyYXcoZmlnLnMxLnRlbXBsYXRlKQogICMgb3V0LmZoIDwtIGdzdWIoIl4iLCAiMjAxOF8wNTMxXyIsIGkpCiAgb3V0LmZoIDwtIGdzdWIoIiQiLCAiX3N0YWNrX3Bsb3QuZXBzIiwgeCkKICBnZ3NhdmUob3V0LmZoLCBwbG90PWZpZy5zMS50ZW1wbGF0ZSwgd2lkdGggPSAyNCwgaGVpZ2h0ID0gNiwgdW5pdHMgPSAiaW4iLCBkZXZpY2UgPSAiZXBzIikgIyAxOCBpbmNoIHdpZHRoIGZvciBzdXBwbGVtZW50YWwgZmlndXJlcywgMjQgaW5jaCB3aWR0aCBmb3IgbWFpbgp9CmBgYAoKYGBge3J9CmZvciAoaSBpbiBuYW1lcyhhbGxfZG9zYWdlKSkgewogIHN0YWNrLnBsb3QoaSkKfQpgYGAKCkNpcmNvcyBwbG90IGdlbmVyYXRpb24gZG9uZSBpbiBhIHN1YmRpcmVjdG9yeSBvZiBgYGByZXN1bHRzYGBg